Рекурсивное удаление дерева - C (СИ)
Формулировка задачи:
Здравствуйте! Школьная задачка, в общем-то. Написать функцию рекурсивного удаления дерева, начиная с определенного элемента.
Суть кода:
1. Вводим исходное дерево.
2. Вводим элемент для удаления.
3. Ищем элемент в дереве.
4. Удаляем сам элемент и всё его поддерево.
Я написал, но работает почему-то неправильно - в функции treeprint ошибка.
Воспроизвести ее можно на следующих данных(см. вложение). Программа не должна заходить в функцию treeprint после того, как вывела элементы 1 и 2, но почему-то заходит и, естественно, натыкаясь на нулевой указатель, аварийно завершается.
Буду благодарен за любую помощь. Подскажите хотя бы, куда копать.
Весь код:
#include <stdio.h>
#include <conio.h>
struct node // Структура узла
{
int info; // Информационное поле
int c; // Счетчик
node *ll, *rl; // Левый и правый указатели
node *parent; //Родитель
};
// -------Функция построения дерева---------
node *tree(node *p, node *dad, int w)
{
if (p == NULL)
{
p = new node;
p->info = w;
p->ll = NULL;
p->rl = NULL;
p->c = 1;
p->parent=dad;
}
else if (w == p->info) // Если такая информация встречалась,
{
p->c = p->c + 1; // то счетчик количества увеличивается на 1
}
else if (w < p->info) // eсли меньше, то идем по левому указателю
{
p->ll = tree(p->ll, p, w);
}
else
{
p->rl = tree(p->rl, p, w); // иначе по правому
}
return p;
}
//--------- Функция обхода дерева -------------
void treeprint(node *p)
{
if (p != NULL)
{
treeprint(p->ll); // по левому указателю
printf("%d\t%d", p->c, p->info);
if(p->parent != NULL)
printf("\tParent: %d", p->parent->info);
else
printf("\tNo parent!");
printf("\n");
treeprint(p->rl); // по правому указателю
}
}
//--------- Функция поиска в дереве по значению узла -------------
node *tree_find(node *&p, int n)
{
if(p!=NULL)
{
if(p->info == n)
return p;
else if(p->info < n)
return tree_find(p->rl, n);
else
return tree_find(p->ll, n);
}
else
return NULL;
}
//--------- Функция удаления дерева, начиная с заданного элемента-------------
void tree_remove (node *p)
{
if(p!=NULL)
{
tree_remove(p->ll);
tree_remove(p->rl);
delete p;
p=NULL;
}
}
int main()
{
node *root; // Рабочий указатель на корень дерева
int w,n,elem; // Буферная переменная, счетчик
root = NULL; //Дерево пустое
printf("Enter amount of trees' elems: ");
scanf("%d", &n);
//вводим дерево
for(int i=0; i<n; i++)
{
scanf("%d", &w);
root=tree(root, NULL, w);
}
treeprint(root);
//вводим элемент для удаления
printf("Enter elem for deletion: ");
scanf("%d", &elem);
node *fordel;
//если элемент с таким значением есть
if(tree_find(root, elem) != NULL)
{
//удаляем его
fordel = tree_find(root, elem);
if(fordel->parent->info < elem)
tree_remove(fordel->parent->rl);
else
tree_remove(fordel->parent->ll);
printf("After deletion: \n");
treeprint(root);
}
getch();
return 0;
}Решение задачи: «Рекурсивное удаление дерева»
textual
Листинг программы
#include <stdio.h>
#include <conio.h>
struct node // Структура узла
{
int info; // Информационное поле
int c; // Счетчик
node *ll, *rl; // Левый и правый указатели
node *parent; //Родитель
};
// -------Функция построения дерева---------
node *tree(node *p, node *dad, int w)
{
if (p == NULL)
{
p = new node;
p->info = w;
p->ll = NULL;
p->rl = NULL;
p->c = 1;
p->parent=dad;
}
else if (w == p->info) // Если такая информация встречалась,
{
p->c = p->c + 1; // то счетчик количества увеличивается на 1
}
else if (w < p->info) // eсли меньше, то идем по левому указателю
{
p->ll = tree(p->ll, p, w);
}
else
{
p->rl = tree(p->rl, p, w); // иначе по правому
}
return p;
}
//--------- Функция обхода дерева -------------
void treeprint(node *p)
{
if (p != NULL)
{
treeprint(p->ll); // по левому указателю
printf("%d\t%d", p->c, p->info);
if(p->parent != NULL)
printf("\tParent: %d", p->parent->info);
else
printf("\tNo parent!");
printf("\n");
treeprint(p->rl); // по правому указателю
}
}
//--------- Функция поиска в дереве по значению узла -------------
node *tree_find(node *&p, int n)
{
if(p!=NULL)
{
if(p->info == n)
return p;
else if(p->info < n)
return tree_find(p->rl, n);
else
return tree_find(p->ll, n);
}
else
return NULL;
}
//--------- Функция удаления дерева, начиная с заданного элемента-------------
void tree_remove (node *&p)
{
if(p!=NULL)
{
tree_remove(p->ll);
tree_remove(p->rl);
delete p;
p=NULL;
}
}
int main()
{
node *root; // Рабочий указатель на корень дерева
int w,n,elem; // Буферная переменная, счетчик
root = NULL; //Дерево пустое
printf("Enter amount of trees' elems: ");
scanf("%d", &n);
//вводим дерево
for(int i=0; i<n; i++)
{
scanf("%d", &w);
root=tree(root, NULL, w);
}
treeprint(root);
//вводим элемент для удаления
printf("Enter elem for deletion: ");
scanf("%d", &elem);
node *fordel;
//если элемент с таким значением есть
if(tree_find(root, elem) != NULL)
{
//удаляем его
fordel = tree_find(root, elem);
if(fordel->parent->info < elem)
tree_remove(fordel->parent->rl);
else
tree_remove(fordel->parent->ll);
printf("After deletion: \n");
treeprint(root);
}
getch();
return 0;
}
Объяснение кода листинга программы
- Структура узла содержит поле
infoдля хранения информации,cдля подсчета количества узлов с одинаковой информацией, поляllиrlдля хранения указателей на левое и правое поддерево соответственно, а также полеparentдля хранения указателя на родительский узел. - Функция
treeсоздает и возвращает новый узел с заданной информацией. Если узел уже существует, увеличивает счетчикcна 1. Рекурсивно вызывает себя для левого и правого поддеревьев, если информация меньше или больше текущей. - Функция
treeprintрекурсивно обходит дерево, печатая информацию, количество потомков и, если есть, родителя каждого узла. - Функция
tree_findрекурсивно ищет узел с заданной информацией. Если узел с такой информацией существует, возвращает его. Если узел с такой информацией не найден, возвращаетNULL. - Функция
tree_removeрекурсивно удаляет дерево, начиная с заданного узла. Если узел пустой, возвращаетNULL. - В функции
mainсоздается указательrootна корень дерева, который изначально равенNULL. Пользователю предлагается ввести количество элементов для создания дерева, а затем сами элементы. После создания дерева выводится его структура. Затем пользователю предлагается ввести элемент для удаления, и если такой элемент существует, он удаляется из дерева. После удаления выводится обновленная структура дерева.