动态查找表:1.表结构本身是在查找过程中动态生成的,即对于给定值 key ,若表中存在关键字等于 key 的记录,则查找成功返回;否则,插入关键字等于 key 的记录。
2.动态查找表主要有二叉树结构和树结构两种类型。二叉树结构有二叉排序树、平衡二叉树等。树结构有B-树、B+树等。
一.二叉排序树:
1.定义:
1)若它的左子树不空,则左子树上所有结点的值均小于根结点的值;
2)若它的右子树不空,则右子树上所有结点的值均大于根结点的值;
3)它的左、右子树也都分别是二叉排序树。
2.存储结构:
struct BtreeNode {
ElemType key; //关键字
BtreeNode *lchild, *rchild;//左、右孩子
} BtreeNode, *Bitree;
3.相关操作:
(1)查找:
BiTree SearchBST(BiTree 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
(2)插入:
1) 若二叉排序树为空树,则新插入的结点为根结点;
2) 若二叉排序树非空,则新插入的结点必为一个新的叶子结点,并且是查找不成功时查找路径上访问的最后一个结点的左孩子或右孩子结点。
Status SearchBST (BiTree T, KeyType key, BiTree f, BiTree &p )
{ //若查找成功,则指针 p 指向该数据元素结点,并返回 TRUE
//否则指针 p 指向查找路径上访问的最后一个结点,并返回 FALSE
//指针 f 指向 T 的双亲,其初始调用值为NULL。
if (!T) { p = f; return FALSE; } // 查找不成功
else
if ( key = T-> data.key ) { p = T; return TRUE; } // 查找成功
else
if ( key < T-> data.key )
SearchBST (T -> lchild, key, T, p ); // 在左子树中查找
else
SearchBST (T-> rchild, key, T, p ); // 在右子树中查找
} // SearchBST
Status InsertBST(BiTree &T, ElemType e )
{
// 当二叉排序树 T 中不存在关键字等于 e.key 的数据元素时,
// 插入 e 并返回 TRUE,否则返回 FALSE
if (!SearchBST ( T, e.key,NULL,p))
{ // 查找不成功
s = (BiTree) malloc (sizeof (BiTNode));
s -> data = e; s -> lchild = s -> rchild = NULL;
if ( !p ) T = s; // 插入 s 为新的根结点
else
if ( e.key < p -> data.key ) p -> lchild = s; // 插入 s 为左孩子
else p -> rchild = s; // 插入 s 为右孩子
return TRUE;
}
else
return FALSE; // 树中已有关键字相同的结点,不再插入
} // Insert BST
(3)建立二叉排序树:
//反复调用二叉排序树的插入算法即可
Bitree Creat (int n) {
//建立含有n个结点的二叉排序树
Bitree T= NULL;
for ( int i=1; i<=n; i++)
{
cin>>x; //输入关键字序列
InsertBST ( T, x);
}
return BST;
}
(4)删除结点,删除后二叉排序树中序遍历依然有序(三种情况):
1)若*p结点为叶子结点,即PL和PR均为空树。
由于删去叶子结点不破坏整棵树的结构,则只需修改其双亲结点的指针。
2)P只有左子树或右子树:
P只有左(右)子树,用P的左(右)孩子代替P; 。
3)P左、右子树均非空
用P的直接前驱(或直接后继)取代P
4.二叉排序树的查找分析:
(1)含有 n 个结点的二叉排序树的平均查找长度和树的形态有关
例如:
图(1)
图(2)
最好情况: ASL= – 1, 树的深度为└ log2n ┘ + 1(向下取整) ,与折半查找中的判定树相同(形态比较均衡);
最坏情况:插入的 n 个元素从一开始就有序, 变成单支树的形态! 此时树的深度为 n;
A SL = (n + 1) / 2 ,查找效率与顺序查找情况相同。
很明显不同的二叉排序树的ASL与形态有关!!!
实验证明,二叉树形态越均衡,ASL越短,那么如何提高形态不均衡的二叉排序树的查找效率?引入平衡二叉树。
二.平衡二叉树(AVL树)
1.概念:|左子树深度-右子树深度| ≤ 1
其中-1,0,1为平衡因子,显然AVL树只能有这三个平衡因子!
2.平衡二叉树的调整:
(1).LL平衡旋转:若在 A 的左子树的左子树上插入
结点,使 A 的平衡因子从 1 增加
至 2, 需要进行一次顺时针旋转。 (以 B 为旋转轴)
(2).RR 平衡旋转:若在 A 的右子树的右子树上插入
结点,使 A 的平衡因子从 -1 改变
为 -2,需要进行一次逆时针旋转。 (以 B 为旋转轴)
(3) .LR平衡旋转:若在 A 的左子树的右子树上插入
结点,使 A 的平衡因子从 1 增加
至 2, 需要先进行逆时针旋转,
再顺时针旋转。 (以插入的结点 B 为旋转轴)
(4).RL平衡旋转:
若在 A 的右子树的左子树上插入
结点,使 A 的平衡因子从 -1 改变
为 -2,需要先进行顺时针旋转,再逆时针旋转。(以插入的结点 B 为旋转轴)