二叉排序树

本文详细介绍了二叉排序树的创建、查找、结点删除和插入操作。在结点删除部分,特别分析了三种不同情况的处理方式:1) 删除结点的左右子树均非空,通过寻找左子树的最大值替换并删除;2) 结点有一个非空子树;3) 结点的左右子树均为空。代码实现中,使用指针parent和p追踪结点,并通过递归处理各种情况,确保树的平衡和正确性。
摘要由CSDN通过智能技术生成

本文代码包括二叉排序树的创建,查找,结点删除,结点插入。以及结点删除代码分析。
代码见下文。

删除结点情况结合代码分析

删除结点值等于key的结点

line 34: 指针 parent 指向 key的父结点 或者 NULL
line 42: 指针 p 指向 key 或者 NULL
line 45:

  1. key的左右子树都非空
  2. key的一个子树为空
  3. key的左右子树都为空

第一种情况:

找key的左子树的最大值,实质是左子树的最右下值,替换掉key,再处理找到的左子树最大值
指针q指向 key的左子树中的最大值
指针q_parent指向 q的父结点
line 54: 找到顶替key结点的值,即q,使得p.data=q.data,然后处理q
line 55: 根据q所在位置的不同分别处理,是 q_parent 的左子树还是右子树来接受q的左子树,见下图

在这里插入图片描述

第二种情况:

语句ABCD可在具体代码中查看,见下文代码

// 使用q保存非空的子树
if
line 63:语句A
else
line 65:语句B
// 使用parent原来保存p结点的指针保存q结点
if
line 70:语句C
else
line 72:语句D

AC,AD,BD,BC四种情况如下图

在这里插入图片描述

上述描述的第二种情况都是p为非根节点的情况

line:67
当p为根时,parent==NULL
line:68
T指向根节点,此时还属于第二种情况,所以让T指向p下的非空结点就可以了,如下图
在这里插入图片描述

第三种情况:

运行line70或者line72,parent的一个子树=NULL,所以p结点就被删掉了。
注:line 31:q=NULL
在这里插入图片描述

代码

typedef struct Node
{
    int data;
    struct Node *left, *right;
} * BSTree;
BSTree CreateBST(int A[], int n)
{
    BSTree bst = NULL;
    for (int i = 0; i < n; i++)
        InsertData(bst, A[i]);
    return bst;
}

void InsertData(BSTree &T, int val)
{
    if (T == NULL)
    {
        T = (BSTree)malloc(sizeof(struct Node));
        T->data = val;
        T->left = T->right = NULL;
    }
    else
    {
        if (T->data < val)
            InsertData(T->right, val);
        else
            InsertData(T->left, val);
    }
}

void DelData(BSTree &T, int key)
{
    if (!T)
        return;

    BSTree p = T, parent = NULL, q = NULL;
    while (p->data != key)
    {
        parent = p;
        if (key < p->data)
            p = p->left;
        else
            p = p->right;
    }

    // not find key
    if (!p)
        return;

    if (p->left != NULL && p->right != NULL)
    {
        q = p->left;
        BSTree q_parent = p;
        while (q->right != NULL)
        {
            q_parent = q;
            q = q->right;
        }
        p->data = q->data;
        if (q_parent == p)
            q_parent->left = q->left;
        else
            q_parent->right = q->left;
        free(q);
        return;
    }
    else if (p->right != NULL)
        q = p->right;
    else if (p->left != NULL)
        q = p->left;

    if (parent == NULL)
        T = q;
    else if (parent->right == p)
        parent->right = q;
    else if (parent->left == p)
        parent->left = q;
    free(p);
}

BSTree FindKey(BSTree T, int key)
{
    if (T)
    {
        if (T->data == key)
            return T;
        else if (T->data > key)
            return FindKey(T->left, key);
        else
            return FindKey(T->right, key);
    }
    return NULL;
}

void Display(BSTree bst)
{
    queue<BSTree> qu;
    if (bst != NULL)
    {
        qu.push(bst);
    }
    while (!qu.empty())
    {
        BSTree bst = qu.front();
        qu.pop();
        cout << bst->data << " ";
        if (bst->left)
            qu.push(bst->left);
        if (bst->right)
            qu.push(bst->right);
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值