如何从二叉树中删除节点?

How to remove node from binary tree?

我修改了一个给定节点的现有程序,它会创建一个二叉树,计算树遍历,但我不完全知道如何删除一个节点。我所需要的只是一个简单的函数,可以从树中删除节点。基本上,函数应该删除节点。例如:

          50                            50
       /     \         delete(20)      /   \
      30      70       --------->    30     70 
     /  \    /  \                     \    /  \ 
   20   40  60   80                   40  60   80






      50                             60
   /     \         delete(50)      /   \
  40      70       --------->    40    70 
         /  \                            \ 
        60   80                           80

我的代码:

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

struct bin_tree {
int data;
struct bin_tree * right, * left;
};
typedef struct bin_tree node;

void insert(node ** tree, int val)
{
    node *temp = NULL;
    if(!(*tree))
    {
        temp = (node *)malloc(sizeof(node));
        temp->left = temp->right = NULL;
        temp->data = val;
        *tree = temp;
        return;
    }

    if(val < (*tree)->data)
    {
        insert(&(*tree)->left, val);
    }
    else if(val > (*tree)->data)
    {
        insert(&(*tree)->right, val);
    }

}

void print_preorder(node * tree)
{
    if (tree)
    {
        printf("%d\n",tree->data);
        print_preorder(tree->left);
        print_preorder(tree->right);
    }

}

void print_inorder(node * tree)
{
    if (tree)
    {
        print_inorder(tree->left);
        printf("%d\n",tree->data);
        print_inorder(tree->right);
    }
}

void print_postorder(node * tree)
{
    if (tree)
    {
        print_postorder(tree->left);
        print_postorder(tree->right);
        printf("%d\n",tree->data);
    }
}

void deltree(node * tree)
{
    if (tree)
    {
        deltree(tree->left);
        deltree(tree->right);
        free(tree);
    }
}

node* search(node ** tree, int val)
{
    if(!(*tree))
    {
        return NULL;
    }

    if(val < (*tree)->data)
    {
        search(&((*tree)->left), val);
    }
    else if(val > (*tree)->data)
    {
        search(&((*tree)->right), val);
    }
    else if(val == (*tree)->data)
    {
        return *tree;
    }
}

void main()
{
    node *root;
    node *tmp;
    //int i;

    root = NULL;
    /* Inserting nodes into tree */
    insert(&root, 9);
    insert(&root, 4);
    insert(&root, 15);
    insert(&root, 6);
    insert(&root, 12);
    insert(&root, 17);
    insert(&root, 2);
    insert(&root, 0);
    /* Printing nodes of tree */
    printf("Pre Order Display\n");
    print_preorder(root);

    printf("In Order Display\n");
    print_inorder(root);

    printf("Post Order Display\n");
    print_postorder(root);
    /* Search node into tree */
    tmp = search(&root, 4);
    if (tmp)
    {
        printf("Searched node=%d\n", tmp->data);
    }
    else
    {
        printf("Data Not found in tree.\n");
    }

    /* Deleting all nodes of tree */
    deltree(root);
}

我正在按照 OP 的要求复制评论。

我不认为要求一个完整的函数就可以。因此,这里有一个思路:首先,找到要删除的节点。那么:

  • 如果节点没有children,只需将其删除(释放内存并将parent的指针设置为NULL)。

  • 如果节点有左 child,找到它的最大值,从子树中删除它并替换那个最大值而不是给定的节点。

  • Else(如果该节点有右child),从右子树中取出最小值插入到该节点的位置。您可以在不删除实际节点(只是子树中的节点)的情况下执行此操作。