平衡二叉樹(AVL樹)
阿新 • • 發佈:2019-02-08
一、平衡二叉樹的定義
平衡二叉樹是由前蘇聯兩位科學家G.M.Adelse-Velskil和E.M.Landis提出,因此一般也稱作AVL樹。AVL樹仍然是一顆二叉查詢樹,只是在其基礎上增加了“平衡”的要求。所謂平衡是指,對AVL樹的任意結點來說,其左子樹與右子樹的高度之差的絕對值不超過1;其中左子樹與右子樹的高度之差稱為該結點的平衡因子。 只要能隨時保證每個結點平衡因子的絕對值不超過1,AVL的高度就始終能保持O(logn)級別。由於需要對每個結點都得到平衡因子,因此需要在樹的結構中加入一個變數height,用來記錄以當前結點為根結點的子樹的高度:struct node{
int v, height; //v為結點的權值,height為當前子樹高度
node *lchild, *rchild; //左右孩子結點地址
};
在這種定義下,如果需要新建一個結點,就可以採用如下寫法:
/**********生成一個新結點,v為結點權值**********/
node* newNode(int v){
node* Node = new node; //申請一個node型變數的地址空間
Node->v = v; //結點權值為v
Node->height = 1; //結點高度初始為1
Node->lchild = Node->rchild = NULL; //初始狀態沒有左右孩子
return Node; //返回新建結點的地址
}
可以通過下面的函式獲取結點root所在子樹的當前高度:
/******獲取以root為根結點的子樹的當前height*******/
int getHeight(node* root){
if(root == NULL){
return 0; //空結點高度為0
}
return root->height;
}
於是根據定義,可以通過下面的函式計算平衡因子:
/*********計算結點root的平衡因子*********/
int getBanlanceFactor(node* root){
return getHeight(root->lchild) - getHeight(root->rchild); //左子樹高度減右子樹高度
}
結點root所在子樹的height等於其左子樹的height與右子樹的height的較大值加1,因此可以通過下面的函式來更新height:
/******更新結點root的height*******/
void updateHeight(node* root){
root->height = max(getHeight(root->lchild), getHeight(root->rchild)) + 1;
}
二、平衡二叉樹的基本操作
1、查詢操作/********search函式查詢AVL樹中資料域為x的結點*********/
void search(node* root, int x){
if(root == NULL){ //空樹,查詢失敗
printf("search failed\n");
return;
}
if(x == root->data){ //查詢成功,訪問之
printf("%d\n", root->data);
}
else if(x < root->data){ //如果x比根結點的資料域小,說明x在左子樹
search(root->lchild, x); //往左子樹搜尋x
}
else{ //如果x比根結點的資料域大,說明x在右子樹
search(root->rchild, x); //往右子樹上搜索x
}
}
2、插入操作
/************左旋(Left Rotation)************/
void L(node* &root){
node* temp = root->rchild; //root指向結點A,temp指向結點B
root->rchild = temp->lchild;
temp->lchild = root;
updateHeight(root); //更新結點A的高度
updateHeight(temp); //更新結點B的高度
root = temp;
}
/***********右旋(Right Rotation)*************/
void R(node* &root){
node* temp = root->lchild; //root指向結點B,temp指向結點A
root->lchild = temp->rchild;
temp->rchild = root;
updateHeight(root); //更新結點B的高度
updateHeight(temp); //更新結點A的高度
root = temp;
}
/**********插入權值為v的結點**********/
void insert(node* &root, int v){
if(root == NULL){ //到達空結點
root = newNode(v);
return;
}
if(v < root->v){ //v比根結點的權值小
insert(root->lchild, v); //往左子樹插入
updateHeight(root); //更新樹高
if(getBalanceFactor(root) == 2){
if(getBalanceFactor(root->lchild) == 1){ //LL型
R(root);
}
else if(getBalanceFactor(root->lchild) == -1){ //LR型
L(root->lchild);
R(root);
}
}
}
else{ //v比根結點的權值大
insert(root->rchild, v); //往右子樹插入
updateHeight(root); //更新樹高
if(getBalanceFactor(root) == -2){
if(getBalanceFactor(root->rchild) == -1){ //RR型
L(root);
}
else if(getBalanceFactor(root->rchild) == 1){ //RL型
R(root->rchild);
L(root);
}
}
}
}
3、AVL樹的建立
/********AVL樹的建立*********/
node* create(int data[], int n){
node* root = NULL; //新建空根結點root
for(int i = 0; i < n; i++){
insert(root, data[i]); //將data[0]~data[n-1]插入AVL樹中
}
return root; //返回根結點
}