二叉排序树删除某一指定结点

来源:互联网 发布:淘宝规则适用者 编辑:程序博客网 时间:2024/05/18 16:17

二叉排序树中删除一个结点对其祖先是没有影响的,但是对其子孙有影响.

先回顾下二叉排序树的定义:

  • 空树是二叉排序树;
  • 左子树所有结点的值小于根节点,右子树所有结点的值大于根节点,递归定义.

设删除的那个结点为root,那么就要在左子树中找一个最大的结点来替换root或者在右子树中找一个最小的结点来替换root

看图:

这里写图片描述

这是一颗二叉排序树,我们删除73这个结点,就会得到下面这张图:

这里写图片描述

可以看到右子树中77这个最小的结点替换了73这个结点,当然,我们也可以让左子树中64这个结点来替换73这个结点.

那么现在的问题就变成了如何找二叉排序树中最大或最小的结点,这个就很容易从图中得出来了:

  • 二叉排序树中最小的结点在最左边,往左孩子一直走,直到为空;
  • 二叉排序树中最大的结点在最右边,往右孩子一直走,直到为空.

有了这个东西,代码就很好写了.


二叉排序树的数据结构:

typedef struct tagBiTree BiTree;typedef BiTree *pBiTree;struct tagBiTree {    int data;    pBiTree lchild, rchild;    tagBiTree() {}    tagBiTree(int data, pBiTree lchild = nullptr, pBiTree rchild = nullptr) :        data(data), lchild(lchild), rchild(rchild) {}};

删除某一指定结点的函数:

void deleteTheNode(pBiTree &p){    auto pre = p;    if (p == nullptr)        return ;    if (!p->lchild) {        p = p->rchild;        delete pre;    } else if (!p->rchild) {        p = p->lchild;        delete pre;    } else {        // to Left        /*        auto q = p, pp = p->lchild;        while (pp->rchild)            q = pp, pp = pp->rchild;        if (q == p) {            pp->rchild = p->rchild;            p = pp;        } else {            q->rchild = pp->lchild;            pp->lchild = p->lchild;            pp->rchild = p->rchild;            p = pp;        }        */        // to Right        auto q = p, pp = p->rchild;        while (pp->lchild)            q = pp, pp = pp->lchild;        if (q == p) {            pp->lchild = p->lchild;            p = pp;        } else {            q->lchild = pp->rchild;            pp->lchild = p->lchild;            pp->rchild = p->rchild;            p = pp;        }        delete pre;    }}

由于在编程的时候不能直接地看二叉树的结构,因此,我编写了中序遍历来检验算法是否正确,如果删除某一指定结点后,中序遍历仍然是排好序,且只少了删除的那个元素,那么算法就是正确的.

完整测试代码:

#include <bits/stdc++.h>using namespace std;typedef struct tagBiTree BiTree;typedef BiTree *pBiTree;struct tagBiTree {    int data;    pBiTree lchild, rchild;    tagBiTree() {}    tagBiTree(int data, pBiTree lchild = nullptr, pBiTree rchild = nullptr) :        data(data), lchild(lchild), rchild(rchild) {}};void buildBiTree(pBiTree &root, int data){    if (root == NULL) {        root = new BiTree(data);        return ;    }    if (root->data > data)        buildBiTree(root->lchild, data);    else        buildBiTree(root->rchild, data);}void midVisit(pBiTree root){    if (root == nullptr)        return ;    midVisit(root->lchild);    cout << root->data << " ";    midVisit(root->rchild);}void deleteTheNode(pBiTree &p){    auto pre = p;    if (p == nullptr)        return ;    if (!p->lchild) {        p = p->rchild;        delete pre;    } else if (!p->rchild) {        p = p->lchild;        delete pre;    } else {        // to Left        /*        auto q = p, pp = p->lchild;        while (pp->rchild)            q = pp, pp = pp->rchild;        if (q == p) {            pp->rchild = p->rchild;            p = pp;        } else {            q->rchild = pp->lchild;            pp->lchild = p->lchild;            pp->rchild = p->rchild;            p = pp;        }        */        // to Right        auto q = p, pp = p->rchild;        while (pp->lchild)            q = pp, pp = pp->lchild;        if (q == p) {            pp->lchild = p->lchild;            p = pp;        } else {            q->lchild = pp->rchild;            pp->lchild = p->lchild;            pp->rchild = p->rchild;            p = pp;        }        delete pre;    }}int main(){    freopen("in", "r", stdin);    freopen("out", "w", stdout);    pBiTree root = nullptr;    int n;    for (cin >> n; n--;) {        int x;        buildBiTree(root, (cin >> x, x));    }    cout << "pre:" << endl;    midVisit(root);    cout << endl;    deleteTheNode(root);    cout << "now:" << endl;    midVisit(root);    cout << endl;    return 0;}

输入&输出:

输入:

1273 15 77 6 23 9 20 27 13 64 11 28

输出:

pre:6 9 11 13 15 20 23 27 28 64 73 77 now:6 9 11 13 15 20 23 27 28 64 77 
原创粉丝点击