查找算法之二叉排序树

二叉排序树

定义及性质

二叉排序树(Binary Sort Tree)又称为二叉搜索树、二叉查找树。
定义:
二叉排序树或是空树,或是满足如下性质的二叉树:
(1)若其左子树非空,则左子树上所有结点的值均小于根结点的值;
(2)若其右子树非空,则右子树上所有结点的值均大于等于根结点的值;
(3)其左右子树本身又各是一棵二叉排序树

在这里插入图片描述
二叉排序树的性质:
中序遍历非空的二叉排序树所得到的数据元素序列是一个按关键字排列的递增有序序列。

二叉排序树的存储结构

typedef struct{
	KeyType key;          //关键字项
	InfoType otherinfo;   //其他数据与
}ElemType;

typedef struct BSTNode{
	ElemType data;             //数据域
	struct BSTNode *lchild, *rchild;  //左右孩子指针
} BSTNode, *BSTree;

BSTree T;  //定义二叉排序树T

二叉排序树操作——查找

  • 若查找的关键字等于跟结点,成功
  • 否则
    • 若小于根结点,查其左子树
    • 若大于根结点,查其右子树
  • 在左右子树上的操作类似

【算法思想】

  1. 若二叉排序树为空,则查找失败,返回空指针。
  2. 若二叉排序树非空,将给定值key于根结点的关键字T->data.key 进行比较:
    ①若key等于T->data.key,则查找成功,返回根结点地址;
    ②若key小于T->data.key,则进一步查找左子树
    ③若key大于T->data.key,则进一步查找右子树
    【算法描述】
BSTree SearchBST(BSTree T,KeyType key){
	if((!T) || key == T->data.key) return T;
	else if(key < T->data.key)
		return SearchBST(T->lchild,key); //左子树中继续查找
	else
		return SearchBST(T->rchild,key); //在右子树中继续查找
}//SearchBST

查找分析

二叉排序树上查找某关键字等于给定值的结点过程,其实就是走上了一条从根到该结点的路径。

比较的关键字次数 = 此结点所在层次数
最多的比较次数= 树的深度

二叉排序树平均查找长度

在这里插入图片描述
含有n个结点的二叉排序树的平均查找长度和树的形态有关

  • 最好情况:初始序列{45,24,53,12,37,93}
    ASL = log₂(n+1)-1;
    树的深度为:[log₂n]+1;
    于折半查找中的判定树相同。
    (形态比较均衡):O(log₂n)
  • 最坏情况:初始序列{12,24,37,45,53,93}
    插入的n个元素从一开始就有序,——变成单支树的形态!
    此时树的深度为n,ASL=(n+1)/2
    查找效率与顺序查找情况相同:O(n)

问题:如何提高形态不平衡的二叉排序树的查找效率?
解决办法:做“平衡化”处理,即尽量让二叉树的形状均衡! 即,实现平衡二叉树!

二叉排序树操作——插入

  • 若二叉排序树为空,则插入结点作为根结点插入到空树中
  • 否则,继续在其左、右子树上查找
    • 树中已有,不在插入
    • 树中没有
      • 查找直至某个叶子结点的左子树或右子树为空为止,则插入结点应为该叶子结点的左孩子或右孩子
        插入的元素一定在叶结点上

从空树出发,经过一系列的查找、插入操作之后,可生成一棵二叉排序树。
例:设查找的关键字序列为
{45,24,53,45,12,24,90}
可生成二叉排序树如下:
在这里插入图片描述

二叉排序树操作——生成

        一个无序序列可通过构造二叉排序树而变成一个有序序列。构造树的过程就是对无序序列进行排序的过程。
        插入的结点均为叶子结点,故无需移动其他结点。相当于在有序序列上插入记录而无需移动其他记录。
但是:
关键字的输入顺序不同,建立的不同二叉排序树。
在这里插入图片描述

扫描二维码关注公众号,回复: 11202484 查看本文章

二叉排序树操作——删除

       从二叉排序树中删除一个结点,不能把以该结点为根的子树都删去,只能删掉该结点,并且还应保证删除后所得的二叉树仍然满足二叉排序树的性质不变
    由于中序遍历二叉排序树可以得到一个递增有序的序列。那么,在二叉排序树中删去一个结点相当于删去有序序列中的一个结点。

  • 将因删除结点而断开的二叉链表重新连接起来
  • 防止重新连接后树的高度增加

(1)被删除的结点是叶子结点:直接删去该结点。(被删关键字 其双亲结点中相应指针域的值改为“空”)
(2)被删除的结点只有左子树或者右子树,用其左子树或者右子树替换它(结点替换)。其双亲结点的相应指针域的值改为“指向被删除结点的左子树或右子树”。
(3)被删除的结点既有左子树,也有右子树。

  • 以其中序前趋值替换之(值替换),然后再删除该前趋结点。前趋是左子树中最大的结点。
  • 也可以用后继替换之,然后再删除该后继结点。后继是右子树中最小的结点。

在这里插入图片描述

C++实现二叉排序树

代码实现点这里


学习笔记内容来自:青岛大学——王卓老师

原创文章 50 获赞 139 访问量 2万+

猜你喜欢

转载自blog.csdn.net/diviner_s/article/details/106061907