简体   繁体   English

使用父指针从二进制搜索树中删除节点

[英]Delete node from binary search tree with parent pointer

I am working on an algorithm to delete a node with a given key from a binary search tree. 我正在研究一种从二进制搜索树中删除具有给定键的节点的算法。 So far, I have been able to come up with the following code: 到目前为止,我已经能够提出以下代码:

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

typedef int ElType;

typedef struct Tree {
    ElType key;
    struct Tree *left;
    struct Tree *right;
    struct Tree *parent;
} Tree;

Tree* InsertBST(Tree* t, int k)
{
    if (t == NULL) {
        Tree* w = (Tree*) malloc(sizeof(Tree));
        w->key = k;
        w->left = NULL;
        w->right = NULL;
        w->parent = NULL;
        return w;
    }

    if (k <= t->key) {
        t->left = InsertBST(t->left, k);
        t->left->parent = t;
    }
    else {
        t->right = InsertBST(t->right, k);
        t->right->parent = t;
    }

    return t;
}

Tree* DeleteMaxOfBST(Tree* t, ElType *deleted_value)
{
    if (t == NULL) {
        *deleted_value = -1;
        return NULL;
    }

    if (t->right == NULL) {
        *deleted_value = t->key;
        Tree* w = t->left;
        w->parent = t->parent;
        free(t);
        return w;
    }

    t->right = DeleteMaxOfBST(t->right, deleted_value);
    return t;
}

Tree* DeleteNodeOfBST(Tree* t, int k)
{
    if (t == NULL) return NULL;

    if (k < t->key) {
        t->left = DeleteNodeOfBST(t->left, k);
        return t;
    }
    else if (k > t->key) {
        t->right = DeleteNodeOfBST(t->right, k);
        return t;
    }
    else if (t->left == NULL) {
        Tree* w = t->right;
        w->parent = t->parent;
        free(t);
        return w;
    }
    else {
        ElType max_left;
        t->left = DeleteMaxOfBST(t->left, &max_left);
        t->key = max_left;
        return t;
    }
}

The general idea is that I want to work with a BST with pointers to parent nodes and be able to delete a node with whichever key I specify while preserving the structure of a BST. 通常的想法是,我想使用带有指向父节点的指针的BST,并能够在保留BST结构的同时使用我指定的任何键删除节点。

My code works for some keys in some trees but crashes for other keys without any apparent pattern. 我的代码对某些树中的某些键有效,但对其他键却没有任何明显的模式就会崩溃。 I then get the following error: 然后,我得到以下错误:

Segmentation fault (core dumped)

I am inclined to think I have messed up the pointers to the parent nodes but cannot quite pinpoint where the fault is. 我倾向于认为我已经弄乱了指向父节点的指针,但不能完全查明故障所在。 I am relatively new to C, so I would appreciate any comments whether pointers are in fact the problem here and how to possibly fix this. 我对C还是比较陌生,因此,无论指针是否实际上是这里的问题以及如何解决此问题,我将不胜感激。

So, without any examples of how your code runs it's hard to say where exactly the segmentation fault is occurring when your program is running. 因此,在没有任何代码运行方式示例的情况下,很难说出程序运行时分段错误发生的确切位置。 When your program encounters a segmentation fault that means that the program is attempting to access memory that, for whatever reason, it is unable to. 当您的程序遇到分段错误时,这意味着该程序正试图访问由于某种原因而无法访问的内存。 This generally means your pointers are trying to point at an address in memory that they shouldn't be. 通常,这意味着您的指针试图指向内存中不应该指向的地址。

My suggestion would be to run the code step by step and see where the problem occurs. 我的建议是逐步运行代码,看看问题出在哪里。 Or find a debugger that can show you the memory issues your program is having. 或者找到一个调试器,它可以向您显示程序所遇到的内存问题。 I know that the program Valgrind exists for Ubuntu and other Linux best machines, but I'm not sure what others are available for other OSes. 我知道Valgrind程序适用于Ubuntu和其他Linux最佳计算机,但是我不确定其他操作系统是否可以使用其他程序。 You can read more about Valgrind here: http://valgrind.org/ . 您可以在这里阅读有关Valgrind的更多信息: http : //valgrind.org/ I use it whenever I need to check for potential memory handling issues in my programs. 每当需要检查程序中潜在的内存处理问题时,我都会使用它。

Other than that, just keep a real close eye on the space that you create using malloc, as well as where your pointers are pointing. 除此之外,只需密切注意使用malloc创建的空间以及指针指向的位置即可。 Make sure to reconnect your tree properly when you delete the given node. 删除给定节点时,请确保正确重新连接树。 Manually handling memory can be a pain, but you'll get the hang of it. 手动处理内存可能会很麻烦,但是您会发现其中的难处。

Here is the source code for C Program for Insertion and Deletion in Binary Search Tree Recursive.................. 这是二进制搜索树递归中插入和删除的C程序的源代码..................

 /*  C Program for Insertion and Deletion in Binary Search Tree Recursive  */

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

struct node
{
    struct node *lchild;
    int info;
    struct node *rchild;
};

struct node *insert(struct node *ptr, int ikey);
void display(struct node *ptr,int level);
struct node *del(struct node *ptr, int dkey);

int main( )
{
    struct node *root=NULL,*ptr;
    int choice,k;
    while(1)
    {
        printf("\n");
        printf("1.Insert\n");
        printf("2.Delete\n");
        printf("3.Display\n");
        printf("4.Quit\n");
        printf("\nEnter your choice : ");
        scanf("%d",&choice);

        switch(choice)
        {
        case 1:
            printf("Enter the key to be inserted : ");
            scanf("%d",&k);
            root = insert(root, k);
            break;
        case 2:
            printf("Enter the key to be deleted : ");
            scanf("%d",&k);
            root = del(root,k);
            break;
         case 3:
             display(root,0);
             break;
         case 4:
            exit(1);
         default:
            printf("\nWrong choice\n");
        }/*End of switch */
    }/*End of while */

    return 0;

}/*End of main( )*/

struct node *insert(struct node *ptr, int ikey )
{
    if(ptr==NULL)
    {
        ptr = (struct node *) malloc(sizeof(struct node));
        ptr->info = ikey;
        ptr->lchild = NULL;
        ptr->rchild = NULL;
    }
    else if(ikey < ptr->info)   /*Insertion in left subtree*/
        ptr->lchild = insert(ptr->lchild, ikey);
    else if(ikey > ptr->info)   /*Insertion in right subtree */
        ptr->rchild = insert(ptr->rchild, ikey);
    else
        printf("\nDuplicate key\n");
    return ptr;
}/*End of insert( )*/

void display(struct node *ptr,int level)
{
    int i;
    if(ptr == NULL )/*Base Case*/
        return;
    else
    {
        display(ptr->rchild, level+1);
        printf("\n");
        for (i=0; i<level; i++)
            printf("    ");
        printf("%d", ptr->info);
        display(ptr->lchild, level+1);
    }

       printf("\n");

}/*End of display()*/


struct node *del(struct node *ptr, int dkey)
{
    struct node *tmp, *succ;

    if( ptr == NULL)
    {
        printf("dkey not found\n");
        return(ptr);
    }
    if( dkey < ptr->info )/*delete from left subtree*/
        ptr->lchild = del(ptr->lchild, dkey);
    else if( dkey > ptr->info )/*delete from right subtree*/
        ptr->rchild = del(ptr->rchild, dkey);
    else
    {
        /*key to be deleted is found*/
        if( ptr->lchild!=NULL  &&  ptr->rchild!=NULL )  /*2 children*/
        {
            succ=ptr->rchild;
            while(succ->lchild)
                succ=succ->lchild;
            ptr->info=succ->info;
            ptr->rchild = del(ptr->rchild, succ->info);
        }
        else
        {
            tmp = ptr;
            if( ptr->lchild != NULL ) /*only left child*/
                ptr = ptr->lchild;
            else if( ptr->rchild != NULL) /*only right child*/
                ptr = ptr->rchild;
            else    /* no child */
                ptr = NULL;
            free(tmp);
        }
    }
    return ptr;
}/*End of del( )*/

Hope it may help you. 希望对您有所帮助。 For more details, Visit here for More Operations on Binary Search tree ---> C Program for Insertion and Deletion in Binary Search Tree Recursive 有关更多详细信息,请访问此处,以获取有关二进制搜索树的更多操作---> 用于在二进制搜索树递归中插入和删除的C程序

and C Program for binary search tree deletion without recursion C程序,无需递归删除二进制搜索树

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

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