二叉搜索树原理及实现

二叉搜索树原理及实现

树形结构是很常见的非线性关系结构,对于该结构的研究和应用是非常丰富的,值得我们用心学习和研究。类似于我们最常见的有序数组中使用的折半查找(二分查找),二叉树中的二叉搜索树也是一种为了方便查找而出现的一种动态结构。不同的是,有序数组是静态数组,根据它的数据分布的规律,我们能够比较指定位置的数据然后排除一些节点的数据比较操作,逐步缩小查找范围。二叉树虽然不能够像数组那样立即定位某个位置,但是它支持动态添加数据,而且它的数据分布也有类似有序数组的规律,通过这种规律也能够排除一些节点的数据比较操作,逐步缩小查找范围。

二叉搜索树(Binary Search Tree,BST),又译为二叉查找树,这两个名称很流行,故本人统一称之为二叉搜索树。

胡凡的《算法笔记》称:二叉查找树是一种特殊的二叉树,又称为排序二叉树、二叉搜索树、二叉排序树。

严蔚敏的《数据结构(C语言版)(第2版)称:二叉排序树(Binary Sort Tree)又称二叉查找树。

程杰的《大话数据结构》(溢彩加强版)称:二叉排序树,又称为二叉查找树。

1 二叉搜索树的定义

二叉搜索树要么为空;要么是满足以下条件的非空二叉树:

1)树中的每个节点都指定一个关键字。为简单起见,我们假设该关键字为整数类型。

2)在根节点的左子树中,节点的关键字(如果有的话)都小于根节点的关键字。

3)在根节点的右子树中,节点的关键字(如果有的话)都大于根节点的关键字。

4)它的左、右子树都是二叉搜索树。

这个定义是递归式的定义,不复杂。

这个定义说明关键字是唯一的,任意两个节点所对应的关键字是不相同的。这个关键字唯一的要求可以去掉,用 小于等于 替换2)中的 小于,用 大于等于 替换3)中的 大于,这样的二叉树可以称为有 重复值的二叉搜索树(binary search tree with duplicates)。

2 二叉搜索树的实现

2.1 节点数据类型

二叉搜索树的节点结构定义如下:

typedef struct BSTNode
{
    int data;   // 节点的数据,即关键字 
    struct BSTNode *lchild, *rchild;  //左右子树的指针
}BSTNode;

2.2 查找

先从根节点查找,若等于要查找的值,就结束查找。如果当前节点比要找的大就查左子树,如果当前元素比要找的小就查找右子树。代码实现如下:

BSTNode* FindBST(int x, BSTNode* t)
{
    if (t == NULL)
    {
        return NULL;
    }
    
    if (x < t->data)
    {
        return FindBST(t->lchild);
    }
    else if (x > t->data)
    {
        return FindBST(t->rchild);
    }
    else if (x == t->data)
    {
        return t;
    }
}

2.3 插入

先查找,若果找到了就什么也不做(或者做一些更新的操作。因为当前我们定义的二叉搜索树的关键字是不重复的)。若找不到,就在终止查找的地方进行插入。实现代码如下:

BSTNode* InsertBST(int x, BSTNode* t)
{
    if (t == NULL)
    {
        t = malloc(sizeof(struct BSTNode));
        if (t == NULL)
        {
            sprintf()
        }
        else
        {
            t->data = x;
            t->lchild = t->rchild = NULL;
        }
    }
    else
    {
        if (x < t->data)
        {
            t->lchild = InsertBST(x, t->lchild);
        }
        else if (x > t->data)
        {
            t->rchild = InsertBST(x, t->rchild);
        }
    }
    return t;
}

对于重复元素的处理:

1)每个节点数据结构增加一个计数的成员。新节点是1,插入一次就增加这个计数,删除一次就减少一下这个计数。这种方法比直接将重复信息放到树里要好。

2)如果关键字是一个具有复杂结构的对象(结构体对象或类对象)时,不能使用方法1)。此时我们可以把相同关键字的节点保存在一个辅助数据结构里,如链表或者另一棵查找树中。

2.4 删除

中最困难的部分是删除操作,因为不能破坏二叉搜索树的结构。

两种方法:

1)找到比删除的关键字小的最大节点(胡凡《算法笔记》称之为被删除节点的前驱),将其覆盖要删除的节点,然后删除前驱节点。

2)找到比删除的关键字大的最小节点(胡凡《算法笔记》称之为被删除节点的后继),将其覆盖要删除的节点,然后删除后驱节点。

该实现代码日后补上,见谅。

该文章会更新,欢迎大家批评指正。

推荐一个零声学院免费公开课程,个人觉得老师讲得不错,
分享给大家:[Linux,Nginx,ZeroMQ,MySQL,Redis,
fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,
TCP/IP,协程,DPDK等技术内容,点击立即学习:
服务器课程:C++服务器

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值