數據結構實驗之查找二:平衡二叉樹

平衡二叉樹

對於二叉查找樹,儘管查找、插入及刪除操作的平均運行時間爲O(logn),但是它們的最差運行時間都是O(n),原因在於對樹的形狀沒有限制。

平衡二叉樹又稱爲AVL樹,它或者是一棵空樹,或者是有下列性質的二叉樹:它的左子樹和右子樹都是平衡二叉樹,且左右子樹的深度之差的絕對值不超過1。二叉樹的的平衡因子BF爲:該結點的左子樹的深度減去它的右子樹的深度,則平衡二叉樹的所有結點的平衡因子爲只可能是:-1、0和1

一棵好的平衡二叉樹的特徵:

(1)保證有n個結點的樹的高度爲O(logn)

(2)容易維護,也就是說,在做數據項的插入或刪除操作時,爲平衡樹所做的一些輔助操作時間開銷爲O(1)

一、平衡二叉樹的構造

在一棵二叉查找樹中插入結點後,調整其爲平衡二叉樹。若向平衡二叉樹中插入一個新結點後破壞了平衡二叉樹的平衡性。首先要找出插入新結點後失去平衡的最小子樹根結點的指針。然後再調整這個子樹中有關結點之間的鏈接關係,使之成爲新的平衡子樹。當失去平衡的最小子樹被調整爲平衡子樹後,原有其他所有不平衡子樹無需調整,整個二叉排序樹就又成爲一棵平衡二叉樹

1.調整方法

(1)插入點位置必須滿足二叉查找樹的性質,即任意一棵子樹的左結點都小於根結點,右結點大於根結點

(2)找出插入結點後不平衡的最小二叉樹進行調整,如果是整個樹不平衡,才進行整個樹的調整。

2.調整方式

(1)LL型

LL型:插入位置爲左子樹的左結點,進行向右旋轉


由於在A的左孩子B的左子樹上插入結點F,使A的平衡因子由1變爲2,成爲不平衡的最小二叉樹根結點。此時A結點順時針右旋轉,旋轉過程中遵循“旋轉優先”的規則,A結點替換D結點成爲B結點的右子樹,D結點成爲A結點的左孩子。
(2)RR型
RR型:插入位置爲右子樹的右孩子,進行向左旋轉

由於在A的右子樹C的右子樹插入了結點F,A的平衡因子由-1變爲-2,成爲不平衡的最小二叉樹根結點。此時,A結點逆時針左旋轉,遵循“旋轉優先”的規則,A結點替換D結點成爲C的左子樹,D結點成爲A的右子樹。
(3)LR型
LR型:插入位置爲左子樹的右孩子,要進行兩次旋轉,先左旋轉,再右旋轉;第一次最小不平衡子樹的根結點先不動,調整插入結點所在的子樹,第二次再調整最小不平衡子樹。

 
 由於在A的左子樹B的右子樹上插入了結點F,A的平衡因子由1變爲了2,成爲不平衡的最小二叉樹根結點。第一次旋轉A結點不動,先將B的右子樹的根結點D向左上旋轉提升到B結點的位置,然後再把該D結點向右上旋轉提升到A結點的位置。
(4)RL型
RL型:插入位置爲右子樹的左孩子,進行兩次調整,先右旋轉再左旋轉;處理情況與LR類似。
以上內容轉自:http://blog.csdn.net/zhuyingqingfen/article/details/6530434感謝大神。
3.建平衡二叉樹

創建平衡二叉樹,我們採用依次插入節點的方式進行。而平衡二叉樹上插入節點採用遞歸的方式進行。遞歸算法如下:

(1)      若該樹爲一空樹,那麼插入一個數據元素爲e的新節點作爲平衡二叉樹的根節點,樹的高度增加1。

(2)      若待插入的數據元素e和平衡二叉樹(BBST)的根節點的關鍵字相等,那麼就不需要進行插入操作。

(3)      若待插入的元素e比平衡二叉樹(BBST)的根節點的關鍵字小,而且在BBST的左子樹中也不存在和e有相同關鍵字的節點,則將e插入在BBST的左子樹上,並且當插入之後的左子樹深度增加1時,分別就下列情況處理之。

(a)    BBST的根節點的平衡因子爲-1(右子樹的深度大於左子樹的深度):則將根節點的平衡因子更改爲0,BBST的深度不變;

(b)    BBST的根節點的平衡因子爲0(左右子樹的深度相等):則將根節點的平衡因子修改爲1,BBST的深度增加1;

(c)    BBST的根節點的平衡因子爲1(左子樹的深度大於右子樹的深度):若BBST的左子樹根節點的平衡因子爲1,則需要進行單向右旋轉平衡處理,並且在右旋處理後,將根節點和其右子樹根節點的平衡因子更改爲0,樹的深度不變;

若BBST的左子樹根節點的平衡因子爲-1,則需進行先向左,後向右的雙向旋轉平衡處理,並且在旋轉處理之後,修改根節點和其左,右子樹根節點的平衡因子,樹的深度不變;

(4)      若e的關鍵字大於BBST的根節點的關鍵字,而且在BBST的右子樹中不存在和e有相同關鍵字的節點,則將e插入到BBST的右子樹上,並且當插入之後的右子樹深度加1時,分別就不同的情況處理之。

(a)      BBST的根節點的平衡因子是1(左子樹的深度大於右子樹的深度):則將根節點的平衡因子修改爲0,BBST的深度不變;

(b)      BBST的根節點的平衡因子是0(左右子樹的深度相等):則將根節點的平衡因子修改爲-1,樹的深度加1;

(c)      BBST的根節點的平衡因子爲-1(右子樹的深度大於左子樹的深度):若BBST的右子樹根節點的平衡因子爲1,則需要進行兩次選擇,第一次先向右旋轉,再向左旋轉處理,並且在旋轉處理之後,修改根節點和其左,右子樹根節點的平衡因子,樹的深度不變;

若BBST的右子樹根節點的平衡因子爲1,則需要進行一次向左的旋轉處理,並且在左旋之後,更新根節點和其左,右子樹根節點的平衡因子,樹的深度不變。

建樹內容轉自:http://blog.csdn.net/guoqingshuang/article/details/50190119感謝大神。

Problem Description
根據給定的輸入序列建立一棵平衡二叉樹,求出建立的平衡二叉樹的樹根。

Input
輸入一組測試數據。數據的第1行給出一個正整數N(n <= 20),N表示輸入序列的元素個數;第2行給出N個正整數,按數據給定順序建立平衡二叉樹。

Output
輸出平衡二叉樹的樹根。

Example Input
5
88 70 61 96 120Example Output
70Hint
  


#include<stdio.h>
#include<stdlib.h>
typedef struct BiTNode{
	int data;
	BiTNode *lchild,*rchild;
	int id;
}BiTNode,*BiTree;
int max(int a,int b){
	return a>b?a:b;
}
int depth(BiTree T){
	if(!T)
	return -1;
	return T->id;
}
BiTree LL(BiTree T){//右旋 
	BiTree q = T->lchild;
	T->lchild = q->rchild;
	q->rchild = T;
	q->id = max(depth(q->lchild),depth(q->rchild))+1;
	T->id = max(depth(T->lchild),depth(T->rchild))+1;
	return q;
}
BiTree RR(BiTree T){//左旋 
	BiTree q = T->rchild;
	T->rchild = q->lchild;
	q->lchild = T;
	q->id = max(depth(q->lchild),depth(q->rchild))+1;
	T->id = max(depth(T->lchild),depth(T->rchild))+1;
	return q;
}
BiTree LR(BiTree T){
	T->lchild = RR(T->lchild);//先左 
	return LL(T);//後右 
}
BiTree RL(BiTree T){
	T->rchild = LL(T->rchild);//先右 
	return RR(T);//後左 
}
void creat(BiTree &T,int key){
	if(T==NULL){
		T= new BiTNode;
		T->data = key;
		T->lchild = T->rchild = NULL;
		T->id = 0;
	}
	else{
		if(key<T->data){
			creat(T->lchild,key);
			if(depth(T->lchild)-depth(T->rchild)>1){
				if(key < T->lchild->data)
				T=LL(T);
				else
				T=LR(T);
			}
		}
		else if(key>T->data){
			creat(T->rchild,key);
			if(depth(T->rchild)-depth(T->lchild)>1){
				if(key>T->rchild->data)
				T=RR(T);
				else
				T=RL(T);
			}
		}
	}
	T->id=max(depth(T->lchild),depth(T->rchild))+1;
}
int main(){
	int n,i;
	int a[22];
	BiTree T;
	T = NULL;
	scanf("%d",&n);
	for(i=0;i<n;i++){
		scanf("%d",&a[i]);
		creat(T,a[i]);
	}
	printf("%d\n",T->data);
	return 0;
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章