Рекурсивное удаление дерева - 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;
}

Объяснение кода листинга программы

  1. Структура узла содержит поле info для хранения информации, c для подсчета количества узлов с одинаковой информацией, поля ll и rl для хранения указателей на левое и правое поддерево соответственно, а также поле parent для хранения указателя на родительский узел.
  2. Функция tree создает и возвращает новый узел с заданной информацией. Если узел уже существует, увеличивает счетчик c на 1. Рекурсивно вызывает себя для левого и правого поддеревьев, если информация меньше или больше текущей.
  3. Функция treeprint рекурсивно обходит дерево, печатая информацию, количество потомков и, если есть, родителя каждого узла.
  4. Функция tree_find рекурсивно ищет узел с заданной информацией. Если узел с такой информацией существует, возвращает его. Если узел с такой информацией не найден, возвращает NULL.
  5. Функция tree_remove рекурсивно удаляет дерево, начиная с заданного узла. Если узел пустой, возвращает NULL.
  6. В функции main создается указатель root на корень дерева, который изначально равен NULL. Пользователю предлагается ввести количество элементов для создания дерева, а затем сами элементы. После создания дерева выводится его структура. Затем пользователю предлагается ввести элемент для удаления, и если такой элемент существует, он удаляется из дерева. После удаления выводится обновленная структура дерева.

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

14   голосов , оценка 3.929 из 5
Похожие ответы