数据结构与算法之二叉排序树(又名二叉查找树,二叉搜索树)

今天看到一句话分享一下,所谓优势只不过比别人深入思考一点而已。

多看书,多思考。

 

二叉排序树(二叉搜索树,二叉查找树)

基本性质:

1.若它的左子树不空,则左子树上所有节点的值均小于它的根结点的值

2.若它的右子树不空,则右子树上所有结点的值均大于它的根节点的值

3.它的左右子树也是二叉排序树

 

应用目的:并不是为了排序,而是为了提高查找和插入删除关键字的速度。

 

二叉排序树的查找算法:

(1)若根节点不为空

                如果根节点key==查找key,返回true

                如果根节点key>查找key,在其左子树查找

                如果根节点key<查找key,在其右子树查找

    否则,返回false;

 

操作:

 

二叉排序树的插入算法:

(1)先检测这个元素是否在树中已经存在。

(2)如果存在,则不进行插入,如果不存在,则进行插入

 

操作:

删除操作:

删除操作比较查找和插入都复杂一些。

分这么几种情况:

(1)删除节点为叶子节点

(2)删除节点仅有左子树或者右子树

(3)删除节点左右子树都有。

1.如果删除的节点是叶子节点的话,我们可以直接删除,对树的结构基本没有影响

2.如果删除的节点仅有左子树或右子树,那么可以将左子树或者右子树移动到删除节点的位置即可。

3.删除节点左右子树都有的情况。

我们可以从它的左子树或者右子树里面找个节点来替代它,找哪个节点呢?我们分析一下二叉排序树的特点可知,它的中序遍历是有序的,所以可以找到它的前一个节点或者后一个节点

举个栗子:

以0 1 2 3 4 5 6 7 8 9

以5作为根节点,我们现在要删除5的话,可以找4或者6来替代它也就是它的直接前驱和直接后继,那4和6在二叉排序树应该在什么位置呢?

在它的左子树的最右节点和右子树的最左节点上。

然后替换。

下面是代码实例:

 

#include<iostream>
#include<cstdio>
using namespace std;
typedef struct tree
{
        int data;
        struct tree *lChild;
        struct tree *rChild;
}BiTode,*BiTree;
typedef bool Status;
typedef int KeyType;
//在根指针T所指二叉排序树中递归地查找其关键字等于Key的数据元素,若查找成功,
//则指针p指向该数据元素节点,并返回true;否则指针p查找路径上访问的最后一个节点并返回FALSE;
//指针f指向T的双亲,其初始调用值为NULL
Status  SearchBST(BiTree T, KeyType key,BiTree f,BiTree *p)
{
        //如果根指针为空则返回false;
        if (T==NULL)
        {
               *p = f;
               return false;
        }
        //如果查找的节点正好是根节点
        else if (T->data == key)
        {
               *p = T;
               return true;
        }
        else if (key > T->data)
        {
               
               return SearchBST(T->rChild,key,T,p);
        }
        else
        {
               f = T;
               return SearchBST(T->lChild,key,T,p);
        }
}
//插入操作
Status InsertBST(BiTree *T,KeyType key)
{
        BiTree p, s;
        //查找这个值在节点中是否存在,如果存在,则不插入,不存在,则插入
        if (!SearchBST(*T, key,NULL,&p))
        {
               //创建一个节点并赋值
               s = (BiTree)malloc(sizeof(BiTode));
               s->data = key;
               s->lChild = s->rChild = NULL;
               //如果p指向空,则直接插入
               if (!p)
               {
                       *T = s;
               }
               else if (key > p->data)
               {
                       p->rChild = s;
               }
               else
               {
                       p->lChild = s;
               }
               return true;
        }
        else
               return false;
}
Status DeleteNode(BiTree *p)
{
        BiTree q, s;
        //只有右子树
        if ((*p)->lChild == NULL)
        {
               q = *p;
               *p = (*p)->rChild;
               free(q);
        }
        //只有左子树
        else if ((*p)->rChild == NULL)
        {
               q = *p;
               *p = (*p)->lChild;
               free(q);
        }
        //左右子树皆不为空,从左子树中找到最右节点即为删除节点的直接前驱,进行替换
        else
        {
               q = *p; s = (*p)->lChild;
               while (s->rChild != NULL)
               {
                       q = s;
                       s = s->rChild;
               }
               //找到直接前驱,将s的值赋予删除节点,释放s。
               (*p)->data = s->data;
               if (q != *p)
               {
                       q->rChild = s->lChild;
               }
               else
               {
                       q->lChild = s->lChild;
               }
               free(s);
        }
        return true;
}
//删除操作
Status DeleteBST(BiTree *T,KeyType key)
{
        //若二叉排序树T中存在关键字等于key的节点,则删除
        //如果不存在,则直接返回false;
        if (!*T) return false;//一直遍历,知道*T为空难,则不存在关键字等于key的元素
        else
        {
               if (key == (*T)->data)
               {
                        return DeleteNode(T);
               }
               else if (key > (*T)->data)
               {
                       return DeleteBST(&(*T)->rChild,key);
               }
               else
               {
                       return DeleteBST(&(*T)->lChild,key);
               }
        }
}
//创建一颗二叉排序树
void CreateBST(KeyType array[], BiTree *p,int len)
{
        int i;
        BiTree T = *p;
        for (i = 0; i < len; i++)
        {
               if (InsertBST(&T, array[i]))
               {
                       cout << "创建了一个值为" << array[i] << "的节点" << endl;
               }
        }
        *p = T;
}
void Delete(BiTree root,KeyType *array,int len)
{
        int i;
        for (i = 0; i < len; i++)
        {
               if (DeleteBST(&root, array[i]))
               {
                       cout << "删除了一个值为" <<array[i]<<"的节点"<< endl;
               }
        }
        if (root == NULL)
        {
               cout << "销毁成功!" << endl;
        }
}
int main(void)
{
        int arr[] = {35,62,37,64,84,96,12,4,75,61};
        int len = sizeof(arr) / sizeof(arr[0]);
        BiTree proot = NULL;
        BiTree p;//用于指向查找元素的节点
        int searchdata;
        CreateBST(arr,&proot,len);
        if (proot != NULL)
        {
               cout << "创建成功!" << endl;
        }
        //查找元素
        cin >> searchdata;
        if (SearchBST(proot, searchdata, NULL, &p))
        {
               printf("元素%d已找到!\n",p->data);
        }
        else
        {
               printf("没有找到此元素!\n");
        }
        Delete(proot,arr,len);
        
        return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值