数据结构复习 【7.3.1 树表的查找--二叉排序树】
引言
当表的插入和删除操作频繁时,为了维护表的有序性,我们需要移动表中的很多记录——可以改用动态查找表,使用几种特殊的树(二叉排序树、平衡二叉树、红黑树、B+、B-、键树等),使表结构在查找过程中动态生成。
一、二叉排序树(二叉搜索树、查找树)
1.定义
二叉排序树或是空树、或是满足如下性质的二叉树:
(1)若其左子树非空,则左子树
上所有节点的值均小于根节点
的值。
(2)若其右子树非空,则右子树
上所有节点的值均大于等于根节点
的值。
(3)其左右子树
本身又是
一棵二叉排序树
。
2.性质
中序遍历非空的二叉排序树得到的数据元素序列,是一个
按关键字排列
的递增有序
序列。
3.查找操作
查找的关键字等于根结点,
查找成功
否则,(1)若小于根结点,查其左子树 (2)如大于根结点,查其右子树
之后在左右子树上的操作类似,查找失败返回空指针。
3.1.相关代码
3.1.1 二叉树排序树的存储结构
typedef struct{
KeyType key; //关键字项
InfoType otherinfo; //其他数据域
} ElemType;
typedef struct BSTNode{
ElemType data; //数据域
struct BSTNode *lchild,*rchild; //左右孩子指针
}BSTNode,*BSTree;
BSTtree T; //定义二叉排序树T
3.1.2 递归查找算法
【算法思想】
(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); //在右子树中继续查找
}
3.2.效率分析
含有n个节点的二叉排序树,其
平均查找长度
和树的形态
有关。
(1)最好情况:完全二叉树,变成判定树
,与折半查找相同
,ASL= log2(N+1) -1,O(log2N)
(2)最坏情况:一开始就有序,变成右斜树
,与顺序查找形同
,ASL=(N+1)/2,O(n)
4.插入操作
若二叉排序树为空,则插入节点作为根节点插入到空树中
否则,继续在其左、右子树上查找
① 树中已有,不再插入
② 树中没有,查找并插入至某个结点的左孩子或右孩子处。
5.生成操作
(1)一个无序序列可以通过构造二叉排序树而变成一个有序序列,
构造树的过程
就是对无序序列进行排序的过程
。
(2)插入
的结点均为叶子结点
,因此无须移动其他节点
。相当于在有序序列上插入记录
而无需移动
其他记录。
(3)关键字的输入顺序不同,建立的二叉排序树不同。
6.删除操作
删除
后要保证所得二叉树仍然满足二叉排序树的性质
不变。
由于中序遍历二叉排序树可以得到一个递增有序的序列,那么删除一个结点相当于删除有序序列中的一个结点。
6.1 删除叶子结点
直接删除
该结点,将双亲结点中对应指针域的值改为空即可
。
6.2 删除含有左子树(或右子树)的结点
用其
左子树
(或右子树)替换自身结点
即可。
6.3 删除含有左、右子树的结点
直接用中序遍历的
前驱节点
或后继节点
来替换自身结点
,其中:
(1)前驱节点
:左子树中最大的节点。(即当前结点-> 左孩子 -> 右孩子 -> 右孩子 …
)
(1)后继节点
:右子树中最小的节点。(即当前结点-> 右孩子 -> 左孩子 -> 左孩子 …
)