标签:
1.动态查找表的特点:表结构本身是在查找过程中动态生成的,即对于给定值key,若表中存在其关键字等于key的记录,则查找成功返回,否则插入关键字等于key的记录。
1 //---------------抽象数据类型动态查找表的定义--------------------- 2 ADT DynamicSearchTable{ 3 数据对象D:D是具有相同特性的数据元素的集合。各个数据元素均含有类型相同,可惟一标识数据元素的关键字。 4 数据关系R:数据元素同属一个集合。 5 基本操作P: 6 InitDSTable(&DT); 7 操作结果:构造一个空的动态查找表DT。 8 DestroyDSTable(&DT); 9 初始条件:动态查找表存在。 10 操作结果:销毁动态查找表DT。 11 SearchDSTable(DT,key); 12 初始条件:动态查找表DT存在,key为和关键字类型相同的给定值。 13 操作结果:若DT中存在其关键字等于key的数据元素,则函数值为该元素的值或在表中的位置,否则为“空”。 14 InsertDSTable(&DT,e); 15 初始条件:动态查找表DT存在,e为待插入的数据元素。 16 操作结果:若DT中不存在其关键字等于e.key的数据元素,则插入e到DT。 17 DeleteDSTable(&DT,key); 18 初始条件:动态查找表DT存在,key为和关键字类型相同的给定值。 19 操作结果:若DT中存在其关键字等于key的数据元素,则删除之。 20 TraverseDSTable(DT,visit()); 21 初始条件:动态查找表DT存在,Visit是对结点操作的应用函数。 22 操作结果:按某种次序对DT的每个结点调用函数Visit()一次且至多一次。一旦Visit()失败,操作失败。 23 }ADT DynamicSearchTable
2.二叉排序树及其查找过程
二叉排序树(Binary Sort Tree) 或者是一棵空树;或者是具有下列性质的二叉树:
(1)若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
(2)若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
(3)它的左、右子树也分别为二叉排序树。
3.二叉排序树查找过程
当二叉排序树不空时,首先将给定值和根结点的关键字比较,若相等,则查找成功,否则将依据给定值和根结点的关键字之间的大小关系,分别在左子树或右子树上继续查找。通常,可取二叉链表作为二叉排序树的存储结构。
1 //---------------------二叉排序树查找算法---------------------- 2 BiTree SearchBST(BiTree T,KeyType key){ 3 //在根指针T所指二叉排序树中递归地查找某关键字等于key的数据元素,若查找成功,则返回指向该数据元素结点的指针,否则返回空指针 4 if((!T)||EQ(key,T->data.key)) 5 return(T); //查找结束 6 else if LT(key,T->data.key) 7 return(SearchBST(T->lchild,key)); //在左子树中继续查找 8 else 9 return(SearchBST(T->rchild,key)); //在右子树中继续查找 10 }//SearchBST
4.二叉排序树的删除
1 //------------------------二叉排序树的查找算法--------------------- 2 Status SearchBST(BiTree T,KeyType key,BiTree f,BiTree &p){ 3 //在根指针T所指二叉排序树中递归地查找其关键字等于key的数据元素,若查找成功,则指针p指向该数据元素结点,并返回TRUE,否则指针p指向查找路径上访问的最后一个结点并返回FALSE,指针f指向T的双亲,其初始掉用值为NULL 4 if(!T) 5 {p = f;return FALSE;} //查找不成功 6 else if EQ(key,T->data.key) 7 {p=T;return TRUE;} //查找成功 8 else if LT(key,T->data.key) 9 return SearchBST(T->lchild,key,T,p); //在左子树中继续查找 10 else 11 return SearchBST(T->rchild,key,T,p); //在右子树中继续查找 12 }//SearchBST
1 //--------------------------二叉排序树插入算法------------------ 2 Status InsertBST(BiTree &T,ElemType e){ 3 //当二叉排序树T中不存在关键字等于e.key的数据元素时,插入e并返回TRUE,否则返回FALSE。 4 if(!SearchBST (T,e.key,NULL,p){ //查找不成功 5 s = (BiTree) malloc (sizeof (BiTNode)); 6 s->data = e; 7 s->lchild = s->rchild = NULL; 8 if (!p) 9 T = s; //被插结点*s为新的根结点 10 else if LT(e.key,p->data.key) 11 p->lchild = s; //被插结点*s为左孩子 12 else 13 p->rchild = s; //被插结点*s为右孩子 14 return TRUE; 15 } 16 else return FALSE; //树中已有关键字相同的结点,不再插入 17 }//InsertBST
5.二叉排序树的删除
假设在二叉排序树上被删结点为*p(指向结点的指针为p),其双亲结点为*f(结点指针为f),且不失一般性,可设*p是*f的左孩子。
下面分3种情况进行讨论:
(1)若*p结点为叶子结点,即P(L)和P(R)均为空树。由于删去叶子结点不破坏整棵树的结构,则只需修改器双亲结点的指针即可。
(2)若*p结点只有左子树P(L)或者只有右子树P(R),此时只要令P(L)或P(R)直接成为其双亲结点*f的左子树即可。显然,作此修改也不破坏二叉排序树的特性。
(3)若*p结点的左子树和右子树均不空。
1 //-----------------------在二叉排序树上删除一个结点的算法--------------- 2 Status DeleteBST(BiTree &T,KeyType key){ 3 //若二叉排序树T中存在关键字等于key的数据元素时,则删除该数据元素结点,并返回TRUE;否则返回FALSE 4 if(!T) 5 return FALSE; //不存在关键字等于key的数据元素 6 else { 7 if (EQ(key,T->data.key)) 8 return Delete(T); //找不到关键字等于key的数据元素 9 else if (LT(key,T->data.key)) 10 return DeleteBST(T->lchild,key); 11 else 12 return DeleteBST(T->rchild,key); 13 } 14 }//DeleteBST
//------------二叉排序树删除操作过程算法---------------- Status Delete (BiTree &p){ //从二叉排序树中删除结点p,并重接它的左或右子树 if (!p->rchild){ //右子树空则需重接它的左子树 q = p; p = p->lchild; free(q); } else if (!p->lchild){ //只需重接它的右子树 q = p; p = p->rchild; free(q); } else { //左右子树均不空 q = p; s = p->lchild; while(s->rchild) { q = s; s = s->rchild } //转左,然后向右到尽头 p->data = s->data; //s指向被删结点的“前驱" if(q!=p) q->rchild = s->lchild; //重接*q的右子树 else q->lchild = s->lchild; //重接*q的左子树 delete s; } return TRUE; }//Delete
6.平衡二叉树
平衡二叉树(Balanced Binary Tree或Height-Balanced Tree)又称AVL树。
它或者是一棵空树,或者是具有下列性质的二叉树:
它的左子树和右子树都是平衡二叉树,且左子树和右子树的深度之差的绝对值不超过1.
若将二叉树上结点的平衡因子BF(Balanced Factor)定义为该结点的左子树的深度减去它的右子树的深度,则平衡二叉树上所有结点的平衡因子只可能是-1、0和1.
只要二叉树上有一个结点的平衡因子的绝对值大于1,则该二叉树就是不平衡的。
7.在平衡二叉排序树BBST上插入一个新的数据元素e的递归算法可描述如下:
(1)若BBST为空树,则插入一个数据元素为e的新结点作为BBST的根结点,树的深度增1;
(2)若e的关键字和BBST的根结点的关键字相等,则不进行插入;
(3)若e的关键字小于BBST的根结点的关键字,而且在BBST的左子树中不存在和e有相同关键字的结点,则将e插入在BBST的左子树上,并且当插入之后的左子树深度增加(+1)时,分别就下列不同情况处理之:
若BBST的左子树根结点的平衡因子为-1,则需进行先向左、后向右双向旋转平衡处理,并且在旋转处理之后,修改根结点和其左、右子树节点的平衡因子,树的深度不变。
(4)若e的关键字大于BBST的根结点的关键字,而且在BBST的右子树中不存在和e 有相同关键字的结点,则将e插入在BBST右子树上,并且当插入之后的右子树深度增加(+1)时,分别就不同情况处理之。其处理操作和(三)中所述相对称。
1 //-------------------二叉排序树的类型定义------------- 2 typedef struct BSTNode{ 3 ElemType data; 4 int bf; //结点的平衡因子 5 struct BSTNode *lchild,*rchild; //左、右孩子指针 6 }BSTNode,*BSTree;
1 //--------------------在平衡处理中进行右旋操作------------------------- 2 void R_Rotate(BSTree &p){ 3 //对以*p为根的二叉排序树作右旋处理,处理之后p指向新的树根结点,即旋转处理之前的左子树的根结点 4 lc = p->lchild; //lc指向的*p左子树根结点 5 p->lchild = lc->rchild; //lc的右子树挂接为*p的左子树 6 lc->rchild = p;p = lc; //p指向新的根结点 7 }//R_Rotate
1 //--------------------在平衡处理中进行左旋操作------------------------- 2 void L_Rotate(BSTree &p){ 3 //对以*p为根的二叉排序树作左旋处理,处理之后p指向新的树根结点,即旋转处理之前的右子树的根结点 4 rc = p->rchild; //rc指向的*p的右子树根结点 5 p->rchild = rc->lchild; //rc的左子树挂接为*p的右子树 6 rc->lchild = p;p = rc; //p指向新的根结点 7 }//L_Rotate
1 //---------------------在平衡的二叉排序树BBST上插入一个新的数据元素e的递归算法----------------- 2 #define LH +1 //左高 3 #define EH 0 //等高 4 #define RH -1 //右高 5 Status InsertAVL(BSTree &T,ElemType e,Boolean &taller){ 6 //若在平衡的二叉排序树T中不存在和e有相同关键字的结点,则插入一个数据元素为e的新结点,并返回1,否则返回0.若因插入而使二叉排序树失去平衡,则作平衡旋转处理,布尔变量taller反映T长高与否 7 if(!T){ //插入新结点,树”长高",置taller为TRUE 8 T = (BSTree) malloc (sizeof(BSTNode)); 9 T->data = e; 10 T->lchild = T->rchild = NULL; 11 T->bf = EH; 12 taller = TRUE; 13 } 14 else { 15 if(EQ(e.key,T->data.key)) //树中已存在和e有相同关键字的结点 16 {taller = FALSE; return 0; } //则不再插入 17 if (LT(e.key,T->data.key)){ 18 if(!InsertAVL(T->lchild,e,taller)) 19 return 0; //未插入 20 if(taller) //已插入到*T的左子树中且左子树“长高” 21 switch(T->bf){ //检查*T的平衡度 22 case LH: //原本左子树比右子树高,需要作左平衡处理 23 LeftBalence(T); taller = FALSE;break; 24 case EH: //原本左、右子树等高,现因左子树增高而使树增高 25 T->bf = LH;taller = TRUE; break; 26 case RH: //原本右子树比左子树高,现在左、右子树等高 27 T->bf = EH;taller = FALSE; break; 28 }//switch(T->bf) 29 }//if 30 else { //应继续在*T的右子树中进行搜索 31 if(!InsertAVL(T->rchild,e,taller)) 32 return 0; //未插入 33 if(taller) //已插入到*T的右子树且右子树长高 34 switch(T->bf){ //检查*T的平衡度 35 case LH: //原本左子树比右子树高,现在左、右子树等高 36 T->bf = EH; taller = FALSE;break; 37 case EH: //原本左、右子树等高,现因右子树增高而使树增高 38 T->bf =RH;taller = TRUE; break; 39 case RH: //原本右子树比左子树高,需要作右平衡处理 40 RightBalance(T);taller = FALSE; break; 41 }//switch(T->bf) 42 }//else 43 }//else 44 return 1; 45 }//InsertAVL
//---------------左平衡处理的算法------------------- void LeftBalace(BSTree &T){ //对以指针T所指结点为根的二叉树作左平衡旋转处理,本算法结束时,指针T指向新的根结点 lc = T->lchild; //lc指向*T的左子树根结点 switch(lc->bf){ //检查*T的左子树的平衡度,并作相应平衡处理 case LH: //新结点插入在*T的左孩子的左子树上,要作单右旋处理 T->bf = lc->bf =EH; R_Rotate(T); break; case RH: //新结点插入在*T的左孩子的右子树上,要作双旋处理 rd = lc->rchild; //rd指向*T的左孩子的右子树根 switch(rd->bf){ //修改*T及其左孩子的平衡因子 case LH:T->bf = RH; lc->bf = EH; break; case EH:T->bf = lc->bf = EH; break; case RH:T->bf = EH;lc->bf = LH; break; }//switch(rd->bf) rd->bf = EH; L_Rotate(T->lchild); //对*T的左子树作左旋平衡处理 R_Rotate(T); //对*T的右旋平衡处理 }//switch(lc->bf) }//LeftBalance
8.平衡树查找的分析
在平衡树上进行查找的时间复杂度为O(logn).
标签:
原文地址:http://www.cnblogs.com/wxb713/p/4340920.html