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