Рекурсивное удаление дерева - 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
. Пользователю предлагается ввести количество элементов для создания дерева, а затем сами элементы. После создания дерева выводится его структура. Затем пользователю предлагается ввести элемент для удаления, и если такой элемент существует, он удаляется из дерева. После удаления выводится обновленная структура дерева.
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д