二叉排序树 建树_二叉排序树

首先二叉排序树也是一棵二叉树,所谓二叉树,就是“任何节点最多只允许两个子节点”,这两个子节点称为左右子节点。如下便是一个二叉树。

1aac2a0a59157dda8da34827eca780eb.png

二叉排序树性质:

1、就是若它的左子树不空,则左子树上所有节点的值均小于它的根节点的值;
2、若它的右子树不空,则右子树上所有节点的值均大于其根节点的值。
3、换句话说就是:任何节点的键值一定大于其左子树中的每一个节点的键值,并小于其右子树中的每一个节点的键值。
如下便是一颗二叉排序树:

526416b64c06f3529ec4e3903c3efb52.png

定义一个二叉排序树结构:

typedef int DataType;

typedef struct BST_Node {

    DataType data;

    struct BST_Node *lchild, *rchild;

}BST_T, *BST_P;

建立二叉排序树,用到Insert_BST方法,在后面:

void CreateBST(BST_P *T, int a[], int n)

{

    int i;

    for (i = 0; i < n; i++)

    {

        Insert_BST(T, a[i]);

    }

}

二叉排序树查找

要在二叉树中找出查找最大最小元素是极简单的事情,从根节点一直往左走,直到无路可走就可得到最小值;从根节点一直往右走,直到无路可走,就可以得到最大值。

递归版查找(找到返回关键字的结点指针,没找到返回NULL):

BST_P Search_BST(BST_P root, DataType key)

{

    if (root == NULL)

        return NULL;

    if (key > root->data) //查找右子树  

        return Search_BST(root->rchild, key);

    else if (key < root->data) //查找左子树  

        return Search_BST(root->lchild, key);

    else

        return root;

}

非递归版查找:

BST_P Search_BST(BST_P root, DataType key)

{

    BST_P p = root;

    while (p) 

    {       

        if (p->data == key)  return p;

        p = (key < p->data) ? p->lchild : p->rchild;

    }

    return NULL;

}

二叉排序树插入

插入新元素时,可以从根节点开始,遇键值较大者就向左,遇键值较小者就向右,一直到末端,就是插入点。

850af7d56b9ca6fd51b75a105e201b73.png

插入代码如下:

void Insert_BST(BST_P *root, DataType data)

{

    //初始化插入节点

    BST_P p = (BST_P)malloc(sizeof(struct BST_Node));

    if (!p) return;

    p->data = data;

    p->lchild = p->rchild = NULL;

    //空树时,直接作为根节点

    if (*root == NULL)

    {

        *root = p;

        return;

    }

    //是否存在,已存在则返回,不插入

    if (Search_BST(root, data) != NULL) return; 

    //进行插入,首先找到要插入的位置的父节点

    BST_P tnode = NULL, troot = *root;

    while (troot)

    {       

        tnode = troot;

        troot = (data < troot->data) ? troot->lchild : troot->rchild;

    }

    if (data < tnode->data)

        tnode->lchild = p;

    else

        tnode->rchild = p;

}

二叉排序树删除

对于二叉排序树中的节点A,对它的删除分为两种情况:
1、如果A只有一个子节点,就直接将A的子节点连至A的父节点上,并将A删除;

2ec44c48934d232fe8bf2ce1552634a4.png

2、如果A有两个子节点,我们就以右子树内的最小节点取代A,怎么得最小节点,前有有说。

57605d152d5cf0d83a49e127db327d4b.png

删除节点代码:

void DeleteBSTNode(BST_P *root, DataType data)

{

    BST_P p = *root, parent = NULL, s = NULL;

    if (!p) return;

    if (p->data == data) //找到要删除的节点了

    {

        /* It's a leaf node */

        if (!p->rchild && !p->lchild) 

            *root = NULL;

        // 只有一个左节点

        else if (!p->rchild&&p->lchild) 

            *root = p->lchild;

        // 只有一个右节点

        else if (!p->lchild&&p->rchild) 

            *root = p->rchild;

        //左右节点都不空

        else 

        {

            s = p->rchild;

            /* the s without left child */

            if (!s->lchild)

                s->lchild = p->lchild;

            /* the s have left child */

            else 

            {

                /* find the smallest node in the left subtree of s */

                while (s->lchild) 

                {

                    /* record the parent node of s */

                    parent = s;

                    s = s->lchild;

                }

                parent->lchild = s->rchild;

                s->lchild = p->lchild;

                s->rchild = p->rchild;

            }

            *root = s;

        }

        free(p);

    }

    else if (data > p->data) //向右找

        DeleteBSTNode(&(p->rchild), data);

    else if (data < p->data) //向左找

        DeleteBSTNode(&(p->lchild), data);

}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值