Рекурсия при заполнении бинарного дерева - C (СИ)
Формулировка задачи:
Есть список с элементами, которые заносятся в дерево по прямому ходу.
Эта функция построения дерева. Она, конечно же, неправильная и глупая. Сначала заполняется левое поддерево до нужного уровня, затем возвращается на этаж выше в дерево, чтобы заполнить правое поддерево, но при этом список тоже возвращается. Т.е получается левое поддерево корня, как на картинке. Но это неправильно. Как исправить функцию, чтобы список не возвращался в положение, которое было до очередного входа в функцию??
struct tree *ForwardStroke(struct List *U, int sizeTree)
{
struct tree *cur=(struct tree*)malloc(sizeof(struct tree));
cur->left=cur->right=NULL;
cur->info=U->n;
U=U->next;
if(sizeTree>1 && U!=NULL)
{
cur->left=ForwardStroke(U, sizeTree-1);
cur->right=ForwardStroke(U, sizeTree-1);
}
return cur;
}Решение задачи: «Рекурсия при заполнении бинарного дерева»
textual
Листинг программы
int Add(Element *curr, int value)
{
if(!curr){ //Если указатель нулевой, то создание корня
//Выделение памяти под элемент
root = (Element *)malloc(sizeof(Element));
if(!root) return 1; //Если память не выделилась - выход
root->parent = NULL;//Инициализация связи с родителем
//Инициализация связи с потомками
root->left = root->right = NULL;
root->value = value; //Запись значения
}else{ //Иначе: не корневой элемент
//Если значение больше значения текущего элемента
if(curr->value < value){
//Если присутствует дочерний элемент слева, то
//вызов функции добавления к дочернему элементу
if(curr->left) return Add(curr->left,value);
}else{ //иначе: если меньше или равно
//Если присутствует дочерний элемент справа, то
//вызов функции добавления к дочернему элементу
if(curr->right) return Add(curr->right,value);
}
//Выделение памяти под новый элемент
Element *tmp = (Element*)malloc(sizeof(Element));
if(!tmp) return 1; //Если память не выделилась - выход
//Инициализация связей с дочерними элементами
tmp->right = tmp->left = NULL;
//Установка связи с родительским элементом
tmp->parent = curr;
tmp->value = value; //Запись значения
//Если значение нового элемента больше, чем значение
//текущего элемента, то добавление в левую ветвь.
//В противном случае - в правую
if(curr->value < value) curr->left = tmp;
else curr->right = tmp;
}
return 0; //Успешное завершение
}
Объяснение кода листинга программы
- Функция
Addпринимает два аргумента: указатель на текущий элементcurrи значениеvalueдля добавления. - Если
currравен NULL, то это означает, что мы добавляем элемент в пустое дерево, поэтому мы выделяем память под новый кореньrootи инициализируем его связи с родителем и потомками (путем вызова функцииmallocи присвоенияNULLзначенийleftиright). Значениеvalueзаписывается вroot->value. - Если
currне равен NULL, то мы проверяем, больше лиvalueзначения текущего элементаcurr. - Если
valueбольше, мы вызываем рекурсивно функциюAddдля левого поддерева (передаемcurr->leftиvalueв качестве аргументов). Если левое поддерево не пустое, то мы продолжаем рекурсивный вызов для правого поддерева. - Если
valueменьше или равноcurr->value, мы вызываем рекурсивно функциюAddдля правого поддерева (передаемcurr->rightиvalueв качестве аргументов). Если правое поддерево не пустое, то мы продолжаем рекурсивный вызов для левого поддерева. - Если оба поддерева пустые, то мы выделяем память под новый элемент
tmpи инициализируем его связи с родительским элементомcurrи дочерними элементами (путем вызова функцииmallocи присвоенияNULLзначенийleftиright). Значениеvalueзаписывается вtmp->value. - Мы добавляем
tmpв левое или правое поддерево в зависимости от того, больше лиvalueзначенияcurr. - В конце функция возвращает
0, что означает успешное завершение. Если в процессе выделения памяти происходит ошибка, функция возвращает1.