二叉排序樹,又稱為二叉查找樹。它或者是一顆空樹,或者具有下列性質的二叉樹。
-
若它的左子樹不空,則左子樹上所有節點的值均小於它的根節點的值;
-
若它的右子樹不空,則右子樹上所有節點的值均大於它的根節點的值;
-
它的左、右子樹也分別為二叉排序樹。
二叉排序樹的難點在於刪除操作
刪除節點有三種情況分析:
a. 葉子節點;(直接刪除即可)
b. 僅有左或右子樹的節點;(上移子樹即可)
c. 左右子樹都有的節點。( 用刪除節點的直接前驅或者直接后繼來替換當前節點,調整直接前驅或者直接后繼的位置)
二叉排序樹的基本操作:
1 #include<bits/stdc++.h>
2 using namespace std; 3
4 typedef struct tree{//二叉樹節點結構定義
5 int date; 6 struct tree *lchild,*rchild;//定義左右子樹
7 }Binode,*Bitree; 8
9 void insert(Bitree t,int date){//插入
10 Bitree p,s,fa; 11 p=t; 12 while(p){//查找date應在的位置
13 if(date<p->date){ 14 fa=p; 15 p=p->lchild; 16 } 17 else if(date>p->date){ 18 fa=p; 19 p=p->rchild; 20 }else{ 21 cout<<"已存在"<<endl; 22 return ; 23 } 24 }//由於buildit為&t,此處fa和p的操作都直接作用於t上。
25 s=(Bitree)malloc(sizeof(Binode));//申請空間
26 s->date=date; 27 s->lchild=s->rchild=NULL; 28 if(s->date<fa->date){ 29 fa->lchild=s; 30 cout<<"已插入"<<s->date<<endl; 31 } 32 else{ 33 fa->rchild=s; 34 cout<<"已插入"<<s->date<<endl; 35 } 36 } 37
38 void Buildit(Bitree &t,int n){//構建二叉排序樹
39 int date; 40 cin>>date; 41 t=(Bitree)malloc(sizeof(Binode));//申請空間
42 t->date=date; 43 t->lchild=t->rchild=NULL;//將左右子樹設為NULL
44 for(int i=1;i<n;i++){//插如n次
45 cin>>date; 46 insert(t,date); 47 cout<<"創建完畢"<<endl; 48 } 49
50 } 51
52 int search1(Bitree t,int key){//搜索節點(非遞歸)
53 Bitree p; 54 p=t; 55 while(p){ 56 if(key< p->date){ 57 p=p->lchild; 58 }else if(key> p->date){ 59 p=p->rchild; 60 } 61 else{ 62 cout<<"已找到"<<p->date<<endl; 63 return 1; 64 } 65 } 66 return 0; 67 } 68
69 int search2(Bitree t,int key){//搜索節點(遞歸)
70 Bitree p; 71 p=t; 72 if(!t){ 73 return 0; 74 } 75 if(p->date==key){ 76 cout<<"已找到"<<p->date<<endl; 77 return 1; 78 }else if(p->date<key){ 79 return search2(p->rchild,key); 80 }else{ 81 return search2(p->lchild,key); 82 } 83 } 84
85 void Delete(Bitree t,int key){//刪除節點
86 Bitree p,cur,par; 87 p=t; 88 while(p){//查找節點位置
89 if(key==p->date){ 90 break; 91 }else if(key<p->date){ 92 par=p; 93 p=p->lchild; 94 }else{ 95 par=p; 96 p=p->rchild; 97 } 98 } 99 if(!p){ 100 return ; 101 } 102 if(!p->lchild){//沒有左子樹
103 if(p==t){//根節點
104 t=p->rchild; 105 }else if(par->lchild==p){//par為p的父節點
106 par->lchild=p->rchild; 107 }else{ 108 par->rchild=p->rchild; 109 } 110 }else{//有左子樹
111 cur=p->lchild; 112 par=cur; 113 while(cur->rchild){ 114 par=cur; 115 cur=cur->rchild; 116 } 117 if(par==p->lchild){//p的左孩子沒有右子樹
118 p->date=par->date; 119 p->lchild=par->lchild; 120 free(par); 121 } 122 else{//有右子樹
123 p->date=cur->date; 124 par->rchild=cur->lchild; 125 free(cur); 126 } 127 } 128 } 129
130 void Inorder(Bitree t){ 131 if(!t) 132 return ; 133 Inorder(t->lchild); 134 cout<<t->date<<" "; 135 Inorder(t->rchild); 136 } 137
138 int main(){ 139 Bitree t; 140 int n,key,select; 141 while(1){ 142 printf(" ------------------\n"); 143 printf(" 1、建立二叉排序樹\n"); 144 printf(" 2、輸出中序遍歷結果\n"); 145 printf(" 3、搜索數據\n"); 146 printf(" 4、刪除數據\n"); 147 printf(" 5、插入數據\n"); 148 printf(" 6、搜索數據(遞歸)\n"); 149 printf(" ------------------\n"); 150 cin>>select; 151 switch(select){ 152 case 1: 153 cin>>n; 154 Buildit(t,n); 155 break; 156 case 2: 157 Inorder(t); 158 cout<<endl; 159 break; 160 case 3: 161 cin>>key; 162 search1(t,key); 163 break; 164 case 4: 165 cin>>key; 166 Delete(t,key); 167 break; 168 case 5: 169 cin>>key; 170 insert(t,key); 171 break; 172 case 6: 173 cin>>key; 174 search2(t,key); 175 break; 176 default: 177 return 0; 178 } 179 } 180 return 0; 181 }