數據結構(二叉排序樹)

二叉排序樹spa

  插入,刪除和查找的效率都比較高(建立時與二叉樹相同)3d

二叉排序樹又稱爲二叉排序樹,若不爲空樹,則有如下性質:指針

  • 若左子樹不爲空,則左子樹上全部結點值均小於根節點的值
  • 若右子樹不爲空,則右子樹上全部結點值均小於根節點的值
  • 他的左右子樹也是二叉樹排序樹(遞歸)

  查找:二叉樹的中序遍歷(從小到大)code

  插入:比根節點小的插入到二叉樹根節點的左邊,反之插入到右邊blog

  刪除:排序

  • 若是待刪除的是葉子結點:直接刪除便可
  • 若待刪除結點只有左孩子或者右孩子,則直接將子樹接到雙親的位置上(代替刪除結點便可)
  • 帶刪除的結點左右子樹都存在:
  1. 用該節點直接前驅或直接後繼來替換該結點(只用數據覆蓋)
  2. 用前驅的左子樹代替前驅,用後繼的右子樹代替後繼
  • 如圖能夠看出要刪除105的話,能夠用他的前驅或者後替代他
  • 前驅爲104,須要注意的是他的前驅只有兩種可能:爲葉子結點或,或者只有左子樹(用爲若是有右子樹的話那麼105的前驅就是他的右子樹了)
  • 後繼用一樣的道理能夠得出,後繼108:爲葉子結點,或只有右子樹
  • 因此刪除一個結點時有兩種方法:用前驅或後繼的數據覆蓋刪除點的數據,用前驅的左子樹接到前驅位置上,或用後繼的右子樹接到後繼上
  • 請思考這裏若是100沒有右子樹時,105的前驅就是他的左子樹,這時就不是將前驅的右子樹接到前驅位置上了,而是將前驅的右左子樹接到前驅位置上

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <malloc.h>
  4 typedef int ElemType;
  5 
  6 typedef struct BiTNode{
  7     ElemType data;
  8     struct BiTNode *lchild;//左孩子
  9     struct BiTNode *rchild;//右孩子
 10 }BiTNode,* BiTree;
 11 
 12 int Delete(BiTree *);
 13 
 14 //遞歸查找二叉樹T中是否存在key
 15 //指針f指向T的雙親,其初始值調用值爲NULL
 16 //若查找成功,則指針p指向該數據元素結點並返回1
 17 //不然指針p指向查找路徑上訪問的最後一個結點,返回0
 18 int SearchBST(BiTree T,int key,BiTree f,BiTree *p){
 19     if(!T){//查找不成功
 20         *p=f;
 21         return 0;
 22     }else if(key==T->data){
 23         *p=T;
 24         return 1;
 25     }else if(key<T->data){
 26         return SearchBST(T->lchild,key,T,p);//在左子樹繼續查找
 27     }else{
 28         return SearchBST(T->rchild,key,T,p);//在右子樹繼續查找
 29     }
 30 }
 31 
 32 //當二叉排序樹T中不存在關鍵字等於key的數據元素樹
 33 //插入key並返回1,否者返回0
 34 int InsertBST(BiTree *T,ElemType key){
 35     BiTree p,s;
 36     if(!SearchBST(*T,key,NULL,&p)){
 37         s=(BiTree)malloc(sizeof(BiTNode));
 38         s->data=key;
 39         s->lchild=s->rchild=NULL;
 40         if(!p){//查找不到key
 41             *T=s;
 42         }else if(key<p->data){
 43             p->lchild=s;
 44         }else{
 45             p->rchild=s;
 46         }
 47         return 1;
 48     }else{
 49         return 0;//樹中已有關鍵字相同的結點,不在插入
 50     }
 51 }
 52 
 53 void cenprintf(BiTree tree){
 54     if(tree){
 55         cenprintf(tree->lchild);
 56         printf("%d  ",tree->data);
 57         cenprintf(tree->rchild);
 58     }
 59 }
 60 
 61 int DeleteBST(BiTree *T,int key){
 62     if(!*T){
 63         return 0;
 64     }else{
 65         if(key==(*T)->data){
 66             return Delete(T);
 67         }else if(key<(*T)->data){
 68             return DeleteBST(&(*T)->lchild,key);
 69         }else{
 70             return DeleteBST(&(*T)->rchild,key);
 71         }
 72     }
 73 }
 74 
 75 int Delete(BiTree *p){
 76     BiTree q,s;
 77     if((*p)->rchild==NULL){
 78         q=*p;
 79         *p=(*p)->lchild;
 80         free(q);
 81     }
 82     else if((*p)->lchild==NULL){
 83         q=*p;
 84         *p=(*p)->rchild;
 85         free(q);
 86     }else{
 87         q=*p;
 88         s=(*p)->lchild;
 89 
 90         while(s->rchild){
 91             //q:始終表明是s是雙親結點
 92             //s:用於尋找刪除結點左子樹上最右邊的結點(值最大的結點)(刪除結點的前驅結點)
 93             q=s;
 94             s=s->rchild;
 95         }
 96         (*p)->data=s->data;
 97         //若是q==p:代表while語句循環體沒有執行,即刪除結點的前驅就是它的左孩子
 98         //若是前驅是它的左孩子,就說明他前驅沒有右孩子;就要把左孩子接到原前驅位置上
 99         //否者表示前驅不爲刪除結點的左孩子,那麼他可能有左孩子,必定沒有右孩子,因此把前驅左孩子接到原前驅位置上
100         if(q != *p){
101             q->rchild=s->lchild;
102         }else{
103             q->lchild=s->lchild;
104         }
105         free(s);
106     }
107     return 1;
108 }
109 
110 void main(){
111     ElemType val;
112     BiTree tree=(BiTree)malloc(sizeof(BiTNode));
113     tree->data=5;
114     tree->lchild=tree->rchild=NULL;
115     printf("請輸入插入樹的值:");
116     scanf("%d",&val);
117     while(-1!=val){
118         InsertBST(&tree,val);
119         printf("請輸入插入樹的值:");
120         scanf("%d",&val);
121     }
122     cenprintf(tree);
123     printf("\n請輸入刪除結點:");
124     scanf("%d",&val);
125     DeleteBST(&tree,val);
126     cenprintf(tree);
127 }

平衡二叉樹遞歸

   排序二叉樹生成的二叉樹結構與輸入的順序有很是重要的關係,若按循序輸入的話就會生成斜二叉樹,那麼斜二叉樹的效率是很是低的,正是有圖這個緣由就出現了平衡二叉樹;it

  • 平衡二叉樹要求:顆樹的左子樹與右子樹的高度最多相差1
  • BF值:樹的左子樹高度減右子樹高度

  1 #define TRUE 1
  2 #define FALSE 0
  3 #define LH 1//左子樹高
  4 #define EH 0//兩子樹同樣高
  5 #define RH -1//右子樹高
  6 typedef int ElemType;
  7 
  8 typedef struct BiTNode{
  9     ElemType data;
 10     int bf;//樹的BF值
 11     struct BiTNode *lchild;//左孩子
 12     struct BiTNode *rchild;//右孩子
 13 }BiTNode,* BiTree;
 14 
 15 //左旋轉
 16 void L_Rotate(BiTree *T)
 17 {
 18     BiTree R = (*T)->rchild;
 19     (*T)->rchild = R->lchild;
 20     R->lchild = *T;
 21     *T = R;
 22     return;
 23 }
 24 //右旋轉
 25 void R_Rotate(BiTree *T)
 26 {
 27     BiTree L = (*T)->lchild;
 28     (*T)->lchild = L->rchild;
 29     L->rchild = *T;
 30     *T = L;
 31     return;
 32 }
 33 
 34 //T 的左邊高,不平衡,使其平衡,右旋轉,右旋轉前先檢查L->bf,
 35 //若是爲RH,L要先進行左旋轉,使T->lchild->bf和T->bf一致
 36 void LeftBalance(BiTree* T)
 37 {
 38     BiTree L,Lr;
 39     L = (*T)->lchild;
 40     Lr = L->rchild;
 41     switch (L->bf)
 42     {
 43         case LH:
 44             L->bf = (*T)->bf =  EH;
 45             R_Rotate(T);
 46             break;
 47         case RH:
 48             switch (Lr->bf)
 49             {
 50                 case LH:
 51                     L->bf = EH;
 52                     (*T)->bf = RH;
 53                     break;
 54                 case EH:
 55                     L->bf = (*T)->bf = EH;
 56                     break;
 57                 case RH:
 58                     L->bf = LH;
 59                     (*T)->bf = EH;
 60                     break;
 61             }
 62             Lr->bf = EH;
 63             L_Rotate(&L);
 64             R_Rotate(T);
 65             break;
 66     }
 67 }
 68 //T 的右邊高,不平衡,使其平衡,左旋轉,左旋轉前先檢查R->bf,
 69 //若是爲LH,R要先進行右旋轉,使T->rchild->bf和T->bf一致
 70 void RightBalance(BiTree* T)
 71 {
 72     BiTree R,Rl;
 73     R = (*T)->rchild;
 74     Rl = R->lchild;
 75     switch(R->bf)
 76     {
 77         case RH:
 78             R->bf = (*T)->bf = EH;
 79             L_Rotate(T);
 80             break;
 81         case LH:
 82             switch(R->bf)
 83             {
 84                 case LH:
 85                     R->bf = RH;
 86                     (*T)->bf = EH;
 87                     break;
 88                 case EH:
 89                     R->bf = (*T)->bf = EH;
 90                     break;
 91                 case RH:
 92                     R->bf = EH;
 93                     (*T)->bf = LH;
 94                     break;
 95             }
 96             Rl->bf = EH;
 97             R_Rotate(&R);
 98             L_Rotate(T);
 99             break;
100     }
101 }
102 
103 //taller:標誌樹有沒有長高,長高返回TRUE,否者FALSE
104 int InsertAVL(BiTree *T,ElemType e,int *taller){
105     if(!(*T)){
106         *T=(BiTree)malloc(sizeof(BiTNode));
107         (*T)->bf=EH;
108         (*T)->data=e;
109         (*T)->lchild=(*T)->rchild=NULL;
110         *taller=TRUE;
111     }
112     else{
113         if(e==(*T)->data){
114             *taller=FALSE;
115             return FALSE;
116         }
117         if(e<(*T)->data){
118             //遞歸向左子樹尋找:
119             //尋找到時返回FALSE:這裏進入判斷繼續FALSE返回(一步步退出遞歸)
120             if(!InsertAVL(&(*T)->lchild,e,taller)){
121                 return FALSE;
122             }
123             if(*taller){
124                 //樹長高了,分析樹是否還平衡,並處理不平衡狀況
125                 switch((*T)->bf){
126                     case LH:
127                         //在左子樹高的狀況下,左子樹又長高了致使的不平衡
128                         LeftBalance(T);//通過處理後,長高的一層被平衡到原倒數層(左旋轉/右旋轉)
129                         *taller=FALSE;
130                         break;
131                     case EH:
132                         //在平衡的狀況,左子樹長高了
133                         (*T)->bf=LH;
134                         *taller=TRUE;
135                         break;
136                     case RH:
137                         //右子樹高的狀況下,左子樹長高了
138                         (*T)->bf=EH;//兩子樹高度相等
139                         *taller=FALSE;
140                         break;
141                 }
142             }
143         }
144         else{
145             //遞歸向右子樹尋找:
146             //尋找到時返回FALSE:這裏進入判斷繼續FALSE返回(一步步退出遞歸)
147             if(!InsertAVL(&(*T)->rchild,e,taller)){
148                 return FALSE;
149             }
150             if(*taller){
151                 //樹長高了,分析樹是否還平衡,並處理不平衡狀況
152                 switch((*T)->bf){
153                     case LH:
154                         //在左子樹高的狀況下,右子樹長高了
155                         (*T)->bf=EH;//兩子樹如今等高
156                         *taller=FALSE;
157                         break;
158                     case EH:
159                         //在平衡的狀況,右子樹長高了
160                         (*T)->bf=RH;
161                         *taller=TRUE;
162                         break;
163                     case RH:
164                         //在右子樹高的狀況下,右子樹又長高了致使的不平衡
165                         RightBalance(T);//通過處理後,長高的一層被平衡到原倒數層(左旋轉/右旋轉)
166                         *taller=FALSE;
167                         break;
168                 }
169             }
170         }
171     }
172 }
LeftBalance的4中狀況;

RightBalance中的四種狀況

相關文章
相關標籤/搜索