7.3.1 二叉排序树的定义
二叉排序树(Binary Sort Tree)又称二叉搜索树、二叉查找树。
1、定义:二叉排序树或是空树,或是满足以下性质的二叉树:
(1)若左子树非空,则左子树上所有结点的值均小于根结点的值;
(2)若右子树非空,则右子树上所有结点的值均大于根结点的值;
(3)左右子树本身又各是一棵二叉排序树。
例如:
![](https://img-blog.csdnimg.cn/a0f51a50ab9d4913807d65e845ecc669.png)
2、二叉排序树的性质
中序遍历非空的二叉排序所得到的数据元素序列是一个按关键字排序的递增有序序列。
3、二叉排序树的查找操作
(1)若查找的关键字等于根结点,查找成功;
(2)否则,若小于根结点,查其左子树;若大于根结点,查其右子树;
(3)在左右子树上的操作类似。
4、二叉排序树的存储
typedef struct
{
KeyType key; //关键字域
InfoType otherinfo //其它数据域
}ElemType;
typedef struct BSTNode
{
ElemType data; //数据域
struct BSTNode *lchild, *rchild; //左右孩子指针
}BSTNode, *BSTree;
5、二叉排序树的递归查找
算法思想:
(1)若二叉排序树为空,则查找失败,返回空指针;
(2)若二叉排序树非空,将给定值key与根结点的关键字T->data.key进行比较:
① 若key == T->data.key,则查找成功,返回根结点地址;
② 若key < T->data.key,则进一步查找左子树;
③ 若key > T->data.key,则进一步查找右子树。
BSTree Search_BST(BSTree T, KeyType key)
{
if ((!T) || key == T->data.key)
return T;
else if (key < T->data.key)
return Search_BST(T->lchild, key);
else if (key > T->data.key)
return Search_BST(T->rchild, key);
return NULL;
}
6、二叉排序树的性能分析
二叉排序树上查找某关键字等于给定值的结点的过程,其实就是走了一条从根结点到该结点的路径。
比较的关键字次数 = 此结点所在层的深度
最多的比较次数 = 树的深度
图1的二叉树的平均查找长度:ASL = (1 + 2 + 2 + 3 + 3 + 3 + 4 + 4 + 5 + 6) / 10 = 3.3
7、二叉排序树的查找分析
含有n个结点的二叉排序树的平均查找长度和树的形态有关。
最好情况:初始序列{45,24,53,12,37,93}, ,树的深度为
,与折半查找的判定树相同。
最坏情况:初始序列{12,24,37,45,53,93},插入的n个元素从一开始就有序,此时树的深度为n,,查找效率与顺序查找的情况相同。
8、二叉树的插入操作
(1)若二叉排序树为空,则插入结点作为根结点插入到空树中;
(2)否则,继续在其左、右子树上查找:
① 树中已有,不再插入
② 树中没有,查找直至某个叶子结点的左子树或右子树为空为止,则插入结点应为该叶子结点的左孩子或右孩子,插入的元素一定在叶子结点上。
9、二叉排序树的生成
从空树出发,经过一系列的查找、插入操作之后,可生成一棵二叉排序树。
例:设查找的关键字序列为{45,24,53,45,12,24,90},可生成二叉排序树如下:
一个无序序列可通过构造二叉排序树而形成一个有序序列,构造树的过程就是对无序序列进行排序的过程。
插入的结点均为叶子结点,故无需移动其它结点。相当于在有序序列中插入记录而无需移动其它记录。
关键字的输入顺序不同,建立的二叉排序树也会不同。
10、二叉排序树的删除操作
从二叉排序树中删除一个结点,不能把以该结点为根的子树都删除,只能删除该结点,并且还应保证删除后所得的二叉树仍然满足二叉排序树的性质不变。
由于中序遍历二叉排序树所得到递增有序序列,那么,在二叉排序树中删除一个结点相当于删除有序序列中的一个结点。
- 将因删除结点而断开的二叉链表重新链接起来;
- 防止重新链接后树的高度增加
(1)被删除的结点是叶子结点,直接删除该结点
(2)被删除的结点是只有左子树或者只有右子树,用其左子树或者右子树替换它
(3)被删除的结点既有左子树,又有右子树:
① 以其中序前趋替换之(值替换),然后再删除该前趋结点,前趋结点是左子树中最大的结点
② 也可以用其后继替换之,然后再删除该后继结点,后继是右子树中最小的结点。