目錄
一、二叉排序樹的定義
二叉排序樹,又稱二叉查找樹(BST),一棵二叉樹或者是空二叉樹,或者是具有如下性質的二叉樹:
左子樹上所有結點的關鍵字均小於根節點的關鍵字;
右子樹上所有結點的關鍵字均大於根節點的關鍵字。
左子樹和右子樹又各是一棵二叉排序樹。
注:
①左子樹結點值<根結點值<右子樹結點值。
②進行中序遍歷,可以得到一個遞增的有序序列。
二、二叉排序樹的查找
若樹非空,目標值與根節點的值比較:
若相等,則查找成功;
若小於根節點,則在左子樹上查找,否則在右子樹上查找。
查找成功,返回結點指針;查找失敗返回NULL
非遞歸實現,最壞空間複雜度O(1)
typedef struct BSTNode{
int key;
struct BSTNode *lchild,rchild;
}BSTNode,*BSTree;
BSTNode *BST_Search(BSTree T,int key){
while(T != NULL && key != T->key){
if( key < T->key)
T = T->lchild;
else
T = T->rchild;
}
return T;
}
遞歸實現,最壞空間複雜度O(h)
BSTNode *BSTSearch(BSTree T,int key){
if(T == NULL)
return NULL;
if(key == T->key)
return T;
else if(key < T->key)
return BSTSearch(T->lchild,key);
else
return BSTSearch(T->rchild,key);
}
三、二叉樹的插入
若原二叉排序樹爲空,則直接插入結點;否則,若關鍵字k小於根節點值,則插入到左子樹,若關鍵字k大於根結點值,則插入到右子
int BST_Insert(BSTree &T,int k){
if(T == NULL){
T = (BSTree)malloc(sizeof(BSTNode));
T->key = k;
T->lchild = T->rchild = NULL;
return 1;
}
else if(k == T->key)
return 0;
else if(k < T->key)
return BST_Insert(T->lchild,k);
else
return BST_Insert(T->rchild,k);
}
四、二叉排序樹的構造
void Creat_BST(BSTree &T,int str[],int n){
T = NULL;
int i = 0;
while(i < n){
BST_Insert(T,str[i]);
i++;
}
}
例1:按照序列str=[50,66,60,26,21,30,70,68]建立BST
例2:按照序列str=[50,26,21,30,66,60,70,68]建立BST
注:不同的關鍵字序列可能得到同款二叉排序樹
例3:按照序列str=[26,21,30,50,60,66,68,70]建立BST
五、二叉排序樹的刪除
先搜索找到目標結點:
①若被刪除結點z是葉子結點,則直接刪除,不會破壞二叉排序樹的性質。
②若結點z只有一顆左子樹或右子樹,則讓z的子樹稱爲z父結點的子樹,替代z的位置
③若結點z有左、右兩棵子樹,則令z的直接後繼(或直接前驅)替代z,然後從二叉排序樹中刪去這個直接後繼(或直接前驅)
六、查找效率分析
查找長度——在查找運算中,需要對比關鍵字的次數稱爲查找長度,反映了查找操作時間複雜度
注:
①若樹高h,找到最下層的一個結點需要對比h次
②最好情況:n個結點的二叉樹最小高度爲[log2n] + 1,平均查找長度 = O(log2n)
③最壞情況:每個結點只有一個分支,樹高h = 結點數n,平均查找長度 = O(n)
查找成功的平均查找長度ASL
①ASL = (1*1 + 2*2 + 3*4 + 4*1) / 8 = 2.625
②ASL = (1*1 + 2*2 + 3*1 + 4*1 + 5*1 + 6*1 + 7*1) / 8 = 3.75
平衡二叉樹:樹上任一結點的左子樹和右子樹的深度之差不超過1。
注:n個結點的二叉樹最小高度爲[log2n] + 1(完全二叉樹),而平衡二叉樹高度與完全二叉樹同等數量級
查找失敗的平均查找長度ASL
①ASL=(3*7 + 4*2) / 9 = 3.22
②ASL=(2*3 + 3 + 4 + 5 + 6 + 7*2) / 9 = 4.22
七、總結