简体   繁体   English

仅包含root的二进制搜索树,删除导致打印无限数量的地址

[英]Binary Search Tree containing only root,deletion causes printing of infinite number of addresses

This code: 这段代码:

  1. inserts 插页
  2. searches 搜索
  3. prints various traversals 打印各种遍历
  4. deletes 删除

Deletion is where the problem lies,i have done this code on my own(so this might not be the regular method).I have seperated deletion into three parts where checking occurs: 删除是问题所在,我自己完成了这个代码(所以这可能不是常规方法)。我将删除分成三个部分,其中检查发生:

  1. if target node is with two child nodes 如果目标节点有两个子节点
  2. if target node is with one child node 如果目标节点具有一个子节点
  3. if target node is with no child node 如果目标节点没有子节点

Every part of this program run correclty,correct outputs(just everything!) except when root is the only node left and we are trying to delete the root. 该程序的每个部分都运行相关,正确的输出(只是一切!),除非root是唯一的节点,我们正在尝试删除根。

It enters nonode function(in the function there is special case for root) and even prints "you have deleted the only node in memory".Gives all the options once again.however selecting any option after that shows an error.In trying printing of various traversals for example it prints an infinite list of addresses on checking traversal and ultimately the .exe file stops instead of printing "no binary tree in memory". 它进入nonode函数(在函数中有root的特殊情况)甚至打印“你删除了内存中的唯一节点”。再次给出所有选项。然后选择任何选项后显示错误。在尝试打印时各种遍历,例如它在检查遍历时打印无限的地址列表,最终.exe文件停止而不是打印“内存中没有二叉树”。

#include <stdio.h>
#include <stdlib.h>

struct bt
{
    struct bt *left;
    int data;
    struct bt *right;
};

struct bt *root=NULL,**sp=NULL;

void insertion(struct bt**,int);
void prtraversal(struct bt**);
void intraversal(struct bt**);
void potraversal(struct bt**);
void search(struct bt**,int);
void del(struct bt **n,int key); 
void nonode(struct bt **n); 
void onenode(struct bt **n);
void bothnode(struct bt **n);

main()
{
    int ch,key;
    printf("******\n\n The program automatically avoids inclusion of repeat numbers\n\n**********");
    while(1)
    {
        printf("\nenter your choice\n1 for insertion\n2 for search\n3 for Various Traversal\n4 for deletion\n5 for exit\n");
        scanf("%d",&ch);
        switch(ch)
        {
        case 1:
            printf("Enter your Key for insertion\n");
            scanf("%d",&key);
            insertion(&root,key);
            break;
        case 2:
            if(root!=NULL)
            {
                printf("Enter your Key for search\n");
                scanf("%d",&key);
                search(&root,key);
            }
            else
            {
                printf("\n NO BINARY TREE IN MEMORY\n");
            }
            break;
        case 3:
            if(root!=NULL)
            {
                printf("\n\nPREORDER TRAVERSAL:");
                prtraversal(&root);
                printf("\n\nINORDER TRAVERSAL:");
                intraversal(&root);
                printf("\n\nPOSTORDER TRAVERSAL:");
                potraversal(&root);
            }
            else
            {
                printf("\n NO BINARY TREE IN MEMORY\n");
            }
            break;
        case 4:
            if(root!=NULL)
            {
                printf("Enter your Key for Delete\n");
                scanf("%d",&key);
                del(&root,key);
            }
            else
            {
                printf("\n NO BINARY TREE IN MEMORY\n");
            }
            break;
        case 5:
            exit(1);
        default:
            printf("\n Wrong Choice\n");
        }
        sp=NULL;
    }
}

void del(struct bt **n,int key)
{
    if((*n)!=NULL)
    {
        if(key<(*n)->data)
            del(&((*n)->left),key);
        else if(key>(*n)->data)
            del(&((*n)->right),key);
        else if(key==(*n)->data)
        {
            printf("\nELEMENT FOUND\n");
            printf("\n DELETION UNDERWAY\n");
            sp=n;
            if(((*n)->right)!=NULL && ((*n)->left)!=NULL)
            {
                bothnode(&((*n)->left));
            }
            else if(((*n)->right)!=NULL && ((*n)->left)==NULL)
            {
                onenode(&((*n)->right));
            }
            else if(((*n)->left)!=NULL && ((*n)->right)==NULL)
            {
                onenode(&((*n)->left));
            }
            else if(((*n)->left)==NULL && ((*n)->right)==NULL)
            {
                nonode(&root);
            }
        }
    }
    else
    {
        printf("\nELEMENT NOT FOUND\n");
    }
}

void nonode(struct bt **n) //deletes the target node without any child,root address is provided to struct bt **n
{
    struct bt **parent=n;//stores address of node just before target node,will be updated in this function
    if(sp!=&root)//target node address stored in sp from a previous function
    {
        while((*n)->data!=(*sp)->data)//to find address of node just before target node and store it in struct bt **parent
        {
            parent=n;//frequent parent update as struct bt **n traverses tree
            if(((*sp)->data)<((*n)->data))
                n=&((*n)->left);
            if(((*sp)->data)>((*n)->data))
                n=&((*n)->right);
        }
        if((*parent)->right==(*sp))//checks if parent's right contains address of target node
        {
            (*parent)->right=NULL;
            free(*sp);
        }
        else if((*parent)->left==(*n))//else checks if parent's left contains address of target node
        {
            (*parent)->left=NULL;
            free(*n);
        }
    }
    else if(sp==&root)//if the root node has to be deleted,no child on either side,only one node in tree
    {
        free(*sp);
        printf("\nYOU DELETED THE ONLY NODE IN MEMORY\n");
    }
}

You are not setting root to NULL when you are deleting a single node from the tree. 从树中删除单个节点时,不将root设置为NULL。 Since, root is global you can set it to NULL inside del(struct bt **n,int key) . 因为root是全局的,你可以在del(struct bt **n,int key)中将它设置为NULL。 By the time you reach this check: 到达此检查时:

else if(((*n)->left)==NULL && ((*n)->right)==NULL)

you already know that you are going to delete the root node because the previous conditions have exhausted all other possibilities. 您已经知道要删除根节点,因为之前的条件已经耗尽了所有其他可能性。 So you can simply free the root node and set it to NULL 因此,您可以简单地释放根节点并将其设置为NULL

else
{
    free(*n);
    *n = NULL;
}

On a side note, your deletion algorithm is very complex. 另外,您的删除算法非常复杂。 In order to delete a node in a BST, you can simply replace its key with that of the largest node in the left subtree or the smallest node in the right subtree and then delete the substituted node. 要删除BST中的节点,只需将其密钥替换为左子树中最大节点或右子树中最小节点的密钥,然后删除替换节点。

Your posted code is flawed in the del() function for removing a leaf-node. 您发布的代码在del()函数中存在缺陷,用于删除叶节点。 You're assuming a leaf node is the root node. 您假设叶节点是根节点。 It might be, but that isn't the point. 它可能是,但这不是重点。

This: 这个:

else if(((*n)->left)==NULL && ((*n)->right)==NULL)
{
    nonode(&root);
}

Should simply do this: 应该简单地这样做:

else nonode(n);

Reason: You already check the prior two conditions, you already know this pointer has no chidden. 原因:您已经检查了前两个条件,您已经知道此指针没有被隐藏。 In actuality, nonode() isn't even needed. 实际上,甚至不需要nonode() You could simply do this: 你可以这样做:

else
{
    free(*n);
    *n = NULL;
}

The whole point of passing in pointers by address is you have access to modify them. 通过地址传递指针的重点是你有权修改它们。 So do so. 所以这样做。 This node is being deleted and you have the address of the pointer that is referencing it. 正在删除此节点,并且您具有引用它的指针的地址。 Delete the node and set that pointer to NULL. 删除节点并将指针设置为NULL。 If that pointer happens to be root so be it; 如果那个指针恰好是root ,那就这样吧; it will be NULL when the function is finished. 函数完成后它将为NULL。

You forgot to set your root to NULL after deleting: 删除后,您忘记将root设置为NULL:

else if(sp==&root)
{
    free(*sp);
    *sp = NULL;                                         // <-- add this line
    printf("\nYOU DELETED THE ONLY NODE IN MEMORY\n");
}

this is a very confusing way to free up a binary tree. 这是释放二叉树的一种非常混乱的方式。 pointers to pointers, different functions for deleting nodes. 指针指针,删除节点的不同功能。 I believe something like this should work find, you can put in your prints where wanted 我相信这样的东西应该可以找到,你可以把你想要的印刷品放进去

void wrap_del(strut tree ** t)
{
    del(*t);
    *t = NULL;
}

void del(struct tree * t)
{
    if (*t == NULL)
        return; //called on a null ptr

    del(t->left);
    del(t->right);
    free(t);
}

this recursive call will go all the way to the bottom of the tree, return when it is called on a null node, and after returning from deleting the left and right, will then free up itself 这个递归调用将一直到树的底部,当它在空节点上调用时返回,并且在从左侧和右侧删除返回后,将自行释放

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM