二叉排序树
二叉排序树,又称为二叉查找树。它或者是一颗空树,或者具有下列性质的二叉树。
-
若它的左子树不空,则左子树上所有节点的值均小于它的根节点的值;
-
若它的右子树不空,则右子树上所有节点的值均大于它的根节点的值;
-
它的左、右子树也分别为二叉排序树。
二叉排序树的难点在于删除操作
删除节点有三种情况分析:
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 }