平衡二叉樹又稱AVL樹。它或者是顆空樹,或者是具有下列性質的二叉樹:它的左子樹和右子樹都是平衡二叉樹,且左子樹和右子樹的深度之差的絕對值不超過1。若將二叉樹節點的平衡因子BF定義爲該節點的左子樹的深度減去它的右子樹的深度,則平衡二叉樹上所有節點的平衡因子只可能爲-1,0,1.只要二叉樹上有一個節點的平衡因子的絕對值大於1,那麼這顆平衡二叉樹就失去了平衡。
假設我們已經有棵平衡二叉樹,現在讓我們來看看插入節點後,原來節點失去平衡後,我們進行選擇的處理方式。
平衡二叉樹多用於查找數據,所以平衡二叉樹又是顆二叉排序樹。
那麼如何創建一顆平衡二叉樹呢?
創建平衡二叉樹,我們採用依次插入節點的方式進行。而平衡二叉樹上插入節點採用遞歸的方式進行。遞歸算法如下:
(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,則需要進行一次向左的旋轉處理,並且在左旋之後,更新根節點和其左,右子樹根節點的平衡因子,樹的深度不變;
下面附上本人的代碼:
- #include <stdio.h>
- #include <stdlib.h>
- /************************************************************************/
- /* 平衡二叉樹---AVL */
- /************************************************************************/
- #define LH +1
- #define EH 0
- #define RH -1
- typedef int ElemType;
- typedef struct BSTNode{
- ElemType data;
- int bf;//balance flag
- struct BSTNode *lchild,*rchild;
- }*PBSTree;
- void R_Rotate(PBSTree* p)
- {
- PBSTree lc = (*p)->lchild;
- (*p)->lchild = lc->rchild;
- lc->rchild = *p;
- *p = lc;
- }
- void L_Rotate(PBSTree* p)
- {
- PBSTree rc = (*p)->rchild;
- (*p)->rchild = rc->lchild;
- rc->lchild = *p;
- *p = rc;
- }
- void LeftBalance(PBSTree* T)
- {
- PBSTree lc,rd;
- lc = (*T)->lchild;
- switch (lc->bf)
- {
- case LH:
- (*T)->bf = lc->bf = EH;
- R_Rotate(T);
- break;
- case RH:
- rd = lc->rchild;
- switch(rd->bf)
- {
- 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;
- }
- rd->bf = EH;
- L_Rotate(&(*T)->lchild);
- R_Rotate(T);
- break;
- }
- }
- void RightBalance(PBSTree* T)
- {
- PBSTree lc,rd;
- lc= (*T)->rchild;
- switch (lc->bf)
- {
- case RH:
- (*T)->bf = lc->bf = EH;
- L_Rotate(T);
- break;
- case LH:
- rd = lc->lchild;
- switch(rd->bf)
- {
- case LH:
- (*T)->bf = EH;
- lc->bf = RH;
- break;
- case EH:
- (*T)->bf = lc->bf = EH;
- break;
- case RH:
- (*T)->bf = EH;
- lc->bf = LH;
- break;
- }
- rd->bf = EH;
- R_Rotate(&(*T)->rchild);
- L_Rotate(T);
- break;
- }
- }
- int InsertAVL(PBSTree* T,ElemType e,bool* taller)
- {
- if ((*T)==NULL)
- {
- (*T)=(PBSTree)malloc(sizeof(BSTNode));
- (*T)->bf = EH;
- (*T)->data = e;
- (*T)->lchild = NULL;
- (*T)->rchild = NULL;
- }
- else if (e == (*T)->data)
- {
- *taller = false;
- return 0;
- }
- else if (e < (*T)->data)
- {
- if(!InsertAVL(&(*T)->lchild,e,taller))
- return 0;
- if(*taller)
- {
- switch ((*T)->bf)
- {
- case LH:
- LeftBalance(T);
- *taller = false;
- break;
- case EH:
- (*T)->bf = LH;
- *taller = true;
- break;
- case RH:
- (*T)->bf = EH;
- *taller = false;
- break;
- }
- }
- }
- else
- {
- if(!InsertAVL(&(*T)->rchild,e,taller))
- return 0;
- if (*taller)
- {
- switch ((*T)->bf)
- {
- case LH:
- (*T)->bf = EH;
- *taller = false;
- break;
- case EH:
- (*T)->bf = RH;
- *taller = true;
- break;
- case RH:
- RightBalance(T);
- *taller = false;
- break;
- }
- }
- }
- return 1;
- }
- bool FindNode(PBSTree root,ElemType e,PBSTree* pos)
- {
- PBSTree pt = root;
- (*pos) = NULL;
- while(pt)
- {
- if (pt->data == e)
- {
- //找到節點,pos指向該節點並返回true
- (*pos) = pt;
- return true;
- }
- else if (pt->data>e)
- {
- pt = pt->lchild;
- }
- else
- pt = pt->rchild;
- }
- return false;
- }
- void InorderTra(PBSTree root)
- {
- if(root->lchild)
- InorderTra(root->lchild);
- printf("%d ",root->data);
- if(root->rchild)
- InorderTra(root->rchild);
- }
- int main()
- {
- int i,nArr[] = {1,23,45,34,98,9,4,35,23};
- PBSTree root=NULL,pos;
- bool taller;
- for (i=0;i<9;i++)
- {
- InsertAVL(&root,nArr[i],&taller);
- }
- InorderTra(root);
- if(FindNode(root,103,&pos))
- printf("\n%d\n",pos->data);
- else
- printf("\nNot find this Node\n");
- return 0;
- }