powered by simpleCommunicator - 2.0.59     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / C++ [игнор отключен] [закрыт для гостей] / Заполнить бинарное дерево
20 сообщений из 20, страница 1 из 1
Заполнить бинарное дерево
    #38046977
Byka
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Как мне корректно составить рекурсивную функцию которая будет заполнять дерево узлами из контейнера данных?
Не могли бы вы привести пример кода? В гугле очень часто пример - когда в main вызывают в цикле функцию создания узла - это не то. Когда я создаю у меня либо только вершина дерева создается либо происходит переполнение стека, что еще печальней.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
struct tree_node {
	tree_node* left;
	tree_node* right;
	int data;

	tree_node(int Data) : left(NULL), right(NULL), data(Data) {
	}
	tree_node() : left(NULL), right(NULL), data(0) {
	}
};

void new_root(const int root_val)
{
	root = new tree_node(root_val);
}

void attach_node(tree_node* new_parent, tree_node * &new_node, int insert_value)
{
	new_node = new tree_node(insert_value);
}

tree_node* insert_node(int ins_val, tree_node *tn, vector<int> d)
{
	if(!tn) tn = root;
	
		if(d[ins_val] < tn->data)
		{
		if(tn->left)
		{
			ins_val++;
			insert_node(ins_val, tn->left, d);
		}
		else
		{
			ins_val++;
			attach_node(tn, tn->left, d[ins_val]);
			
			return tn->left;
		}
		}
		else 
		{
			if(tn->right)
			{
				ins_val++;
				insert_node(ins_val, tn->right, d);
			}
			else 
			{
				ins_val++;
				attach_node(tn, tn->right, d[ins_val]);
				
				return tn->right;
			}
		}
	
}


я знаю, что функция проходить один раз - заносит в правую часть узел и выходит из функции... как мне правильно устроить рекурсию?
...
Рейтинг: 0 / 0
Заполнить бинарное дерево
    #38047076
pirovindos
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Byka,
В insert_node не по всем логическим путям есть возвращаемое значение.
...
Рейтинг: 0 / 0
Заполнить бинарное дерево
    #38047720
Byka
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
pirovindos, здесь в конце? я не понимаю, как происходит заполнение дерева? Сначала корень, потом мы сравниваем пришедшее значение со значением корня, если новое меньше корня - то (если левое поддерево есть или же его создаем) на левое поддерево (tr->left) присваеваем значение (для этого рекурсивно вызываем эту же функцию) после чего получается мы уже работаем с новым узлом которое левое поддерево? Как мы тогда возращаемся к корню для того что бы заполнить правое поддерево и все входящие к нему поддеревья?

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
...
	else 
			{
				ins_val++;
				attach_node(tn, tn->right, d[ins_val]);
				
				return tn->right;
			}
		}
	return tn;
}
...
Рейтинг: 0 / 0
Заполнить бинарное дерево
    #38047799
Byka
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Нашел алгоритм
Теперь осталось написать функцию нормально
...
Рейтинг: 0 / 0
Заполнить бинарное дерево
    #38048137
pirovindos
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Byka,

Приведите вызывающий код. Откуда вызывается insert_node первый раз?
...
Рейтинг: 0 / 0
Заполнить бинарное дерево
    #38048188
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Byka,

На самом деле не нужна тут никакая рекурсия.
...
Рейтинг: 0 / 0
Заполнить бинарное дерево
    #38048195
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В смысле, можно делать и рекурсией, и циклом, но циклом правильнее, в С не оптимизируется хвостовой рекурсия, поэтому стек будет расти на глубину дерева, а это не очень правильно.
...
Рейтинг: 0 / 0
Заполнить бинарное дерево
    #38048492
Byka
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
pirovindos,

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
int main...
{
...
vector<int> data; 
...//задаем вектору данные
insert_node root(data[0]);
insert_node(0, &root, data);
}
...
Рейтинг: 0 / 0
Заполнить бинарное дерево
    #38048502
Byka
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
MasterZiv, циклом - я видел примеры, но думал что это не самый лучший вариант. Дело в том, что я хотел еще спросить, как правильно передавать переменные в рекурсивную функцию, что бы не было переполнения стека? По значению?
...
Рейтинг: 0 / 0
Заполнить бинарное дерево
    #38048507
Byka
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Ага, хотя в случае, если это именно хвостовая рекурсия - то лучше применить цикл?...
...
Рейтинг: 0 / 0
Заполнить бинарное дерево
    #38048561
Byka
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Товарищи, где можно почитать про рекурсию в С++? Что бы полностью разобраться.
...
Рейтинг: 0 / 0
Заполнить бинарное дерево
    #38048749
pirovindos
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Byka,

1. Где-то должна быть проверка того, что входной вектор d исчерпан.
2. Наверное, не нужно делать ins_val++ перед рекурсивным вызовом insert_node внутри insert_node.

P.S. Решать такие задачи рекурсией, по-моему, нормально, если контролировать высоту дерева.
...
Рейтинг: 0 / 0
Заполнить бинарное дерево
    #38048769
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
BykaТоварищи, где можно почитать про рекурсию в С++? Что бы полностью разобраться.

А что ты хочешь прочитать про рекурсию в С++ ?

В С++ функция может вызывать саму себя рекурсивно.
Вот собственно и всё про рекурсию в С++.
...
Рейтинг: 0 / 0
Заполнить бинарное дерево
    #38048779
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
BykaMasterZiv, циклом - я видел примеры, но думал что это не самый лучший вариант.


Это самый лучший вариант.

Byka Дело в том, что я хотел еще спросить, как правильно передавать переменные в рекурсивную функцию, что бы не было переполнения стека? По значению?


А как ни передавай, всё равно будет переполнение стека.
Даже вообще ничего можно не передавать (функцию без параметров вызывать) -- и будет всё равно стек переполняться.
Стек вызовов -- это стуктура с ограниченным размером, поэтому он всегда может переполнится.
Оно конечно, по идее в дереве поиска высота всегда достаточно маленькая (она расчитывается как логарифм от числа объектов),
но чисто теоретически алгоритмы, построенные на рекурсии, будут потенциально переполняться.
На циклах -- никогда.

Чисто теоретически, применительно к этой задаче, я просто не думаю, что рекурсия -- это лучший способ выражения данного алгоритма.
...
Рейтинг: 0 / 0
Заполнить бинарное дерево
    #38048782
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
BykaАга, хотя в случае, если это именно хвостовая рекурсия - то лучше применить цикл?...

Блин, ты как Моисей, правда.
Я такое где-то говорил ?
...
Рейтинг: 0 / 0
Заполнить бинарное дерево
    #38048795
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
BykaАга, хотя в случае, если это именно хвостовая рекурсия - то лучше применить цикл?...

Если это хвостовая рекурсия, то потенциально алгоритм можно выполнять так, чтобы стек вызовов не рос, а оставался постоянным.
Тогда всё равно, записывать алгоритм через рекурсию или через цикл.
Если рекурсия не хвостовая, то стек вызовов будет всегда рости.

Но проблема ещё в том, что С и С++ особенно не стремяться оптимизировать хвостовую рекурсию.
Т.е. возможно существуют какие-то компиляторы, которые это умеют делать, но в массе этого не происходит.
(для примера компилятор лиспа, который это не делает, принято считать ущербным и не годным для работы).
...
Рейтинг: 0 / 0
Заполнить бинарное дерево
    #38049841
m_Sla
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
BykaMasterZiv, циклом - я видел примеры, но думал что это не самый лучший вариант. Дело в том, что я хотел еще спросить, как правильно передавать переменные в рекурсивную функцию, что бы не было переполнения стека? По значению?На платформе 8086 каждый вызов функции увеличивает стек:
1. на стек ложатся параметры функции (если передача параметров через стек)
2. на стек ложится адрес возврата из функции
3. на стеке отводится место под локальные переменные функции
ИМХО рекурсия - зло.
...
Рейтинг: 0 / 0
Заполнить бинарное дерево
    #38050901
Byka
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Благодарю, прояснили ситуацию:)
Но, пока что у меня получилось сделать только таким образом:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
*tree_node* insert_node(int ins_val, tree_node *tn, vector<int> d)
{
	if(ins_val > d.size()-1)
		return root;
	if(!tn) tn = root;
		if(d[ins_val] < tn->data)
		{
		if(tn->left)
		{		
			insert_node(ins_val, tn->left, d);		
		}
		else
		{	
			tn->left = new tree_node(d[ins_val]);	
		}
		}
		else 
		{
			if(tn->right)
			{			
				insert_node(ins_val, tn->right, d);			
			}
			else 
			{		
				tn->right = new tree_node(d[ins_val]);		
			}
		}
		return tn;
}
...
int main ... {
...
for(int i = 1; i != data.size()-1; i++)
	{
		insert_node(i, &root, data);
	}
...
}


Вот пытаюсь построить BST, но пока что получается один уровень построить
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
tree_node* insert_node(int index, int left, int right, tree_node *tn, vector<int> d)
{
	int temp_index;	
	if(right < left)
		return NULL;
	if(!tn) tn = root;
		if(tn->left)
		{		
			insert_node(index, index - 1, right, tn->left, d);			
		}
		else
		{
			temp_index = (left + index)/2;
			tn->left = new tree_node(d[temp_index]);			
		}		 
		if(tn->right)
			{			
				insert_node(index, left, index + 1, tn->right, d);			
			}
			else 
			{
				temp_index = (index + right)/2;
				tn->right = new tree_node(d[temp_index]);				
			}
		return tn;
}
...
int main ... {
...
data.push_back(1); data.push_back(6); data.push_back(10); data.push_back(3); data.push_back(14); data.push_back(8); 
	sort(data.begin(), data.end());
	int index = (0 + data.size())/2;
	tree_node root(data[index]);
	insert_node(index, 0, data.size()-1, &root, data);
...
}


В результате
10
8
3

Как лучше организовать код?
...
Рейтинг: 0 / 0
Заполнить бинарное дерево
    #38051229
Byka
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
...
Рейтинг: 0 / 0
Заполнить бинарное дерево
    #38053848
Byka
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
...
vector<int> numbers;
....

struct Tree
{
	char data;
	Tree *left;
	Tree *right;  
	Tree *parent;  
};

Tree *addToBST(vector<int> numbers, int start, int end)
{
	if(end < start) return NULL;
	int mid = (start + end)/2;

	Tree *r = new Tree;
	r->data = numbers[mid];
	r->left = addToBST(numbers, start, mid-1);
	r->right = addToBST(numbers, mid+1, end);
	return r;
}

Tree *createMinimalBST(vector<int> numbers, int size)
{
	return addToBST(numbers,0,size-1);
}

void Print_BinaryTree(Tree* Node, int l) {
	int i;
	if(Node != NULL) {
		Print_BinaryTree(Node->right, l+1);
		for(i=0; i<l; i++) cout << "    ";
		printf("%4ld", Node->data);
		Print_BinaryTree(Node->left, l+1);
	}
	else cout << endl;
}

int _tmain(int argc, _TCHAR* argv[])
{
		numbers.push_back(3);
		numbers.push_back(6);
		numbers.push_back(14);
		numbers.push_back(8);
		numbers.push_back(10);
		numbers.push_back(1);
		sort(numbers.begin(), numbers.end());
		Tree *newRoot = createMinimalBST(numbers,numbers.size());
		Print_BinaryTree(newRoot, 0);
	getchar();
	return 0;
}
...
Рейтинг: 0 / 0
20 сообщений из 20, страница 1 из 1
Форумы / C++ [игнор отключен] [закрыт для гостей] / Заполнить бинарное дерево
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]