Contents
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314

#include <cstdio>
#include <cstdlib>
#include <queue>
#include <stack>
//查找值这类不修改原数据的行为,则用pnode,要插入,删除,建树,则用pnode* 指向指针的指针
typedef struct searchtree{
int key;
struct searchtree *lchild; //左孩子指针 //注意这里指向该结构的指针还是要用原名字定义
struct searchtree *rchild; //右孩子指针
struct searchtree *parent; //指向父节点指针
}node, *pnode;

//往二叉查找树中插入结点
//插入的话,可能要改变根结点的地址,所以传的是二级指针
void insert_node(pnode *root, int key) //指向指针的指针
{

//初始化插入结点
pnode p = (pnode)malloc(sizeof(node));
p->key = key;
p->lchild = p->rchild = p->parent = NULL;
//空树时,直接作为根结点
if((*root) == NULL)
{
(*root) = p;
return ;
}
//插入到当前结点(*root)的左孩子
if((*root)->lchild == NULL && (*root)->key > key)
{
p->parent = (*root);
(*root)->lchild = p;
return ;
}
//插入到当前结点(*root)的右孩子
if((*root)->rchild == NULL && (*root)->key < key)
{
p->parent = (*root);
(*root)->rchild = p;
return ;
}
if((*root)->key > key)
insert_node(&(*root)->lchild, key);
else if((*root)->key <key)
insert_node(&(*root)->rchild, key);
else //等于的话就不插入
return ;
}

//查找元素,找到返回关键字的结点指针,没找到返回NULL
pnode searchnode(pnode root, int key)
{

if(root == NULL)
return NULL; //没找到返回NULL
if(key < root->key)
return searchnode(root->lchild,key);
else if(key > root->key)
return searchnode(root->rchild,key);
else
return root;
}

//查找最小关键字,空树时返回NULL
pnode searchmin(pnode root)
{

pnode p = root;
if(p == NULL)
return NULL;
else
{
while(p->lchild)
p = p->lchild;
}
return p;
/*
if(root == NULL)
return NULL;
if(root->lchild == NULL)
return root;
else //一直往左孩子找,直到没有左孩子的结点
return searchmin(root->lchild);*/

}

//查找最大关键字,空树时返回NULL
pnode searchmax(pnode root)
{

pnode p = root;
if(p == NULL)
return NULL;
else
{
while(p->rchild != NULL)
p = p->rchild;
}
return p;
/*
if(root == NULL)
return NULL;
if(root->rchild == NULL)
return root;
else //一直往右孩子找,直到没有右孩子的结点
return searchmax(root->rchild);*/

}

//查找某个结点的前驱
pnode searchpredecessor(pnode p)
{

//空树
if(p == NULL)
return NULL;
//有左子树、左子树中最大的那个
if(p->lchild != NULL)
return searchmax(p->lchild);
//无左子树,查找某个结点的右子树遍历完了
else
{
if(p->parent == NULL)
return NULL;
//向上寻找前驱
while(p)
{
if(p->parent->rchild == p)
break;
p = p->parent;
}
return p->parent;
}
}

//查找某个结点的后继
pnode searchsuccessor(pnode p)
{

if(p == NULL)
return NULL;
if(p->rchild) //有右子树、右子树中最小的那个
return searchmin(p->rchild);
else //无右子树,查找某个结点的左子树遍历完了
{
if(p->parent == NULL)
return NULL;
//向上寻找后继
while(p)
{
if(p->parent->lchild == p)
break;
p = p->parent;
}
return p->parent;
}
}

//根据关键字删除某个结点,删除成功返回1,否则返回0
//如果把根结点删掉,那么要修改数据,所以传二级指针
int deletenode(pnode *root, int key) //pnode *是指向指针的指针
{

//查找到要删除的结点
pnode p = searchnode((*root),key);
if(!p)
return 0;
//1.被删除点是叶子结点,直接删除
if(p->lchild == NULL && p->rchild == NULL)
{
//只有一个元素,删完之后变成一颗空树
if(p->parent == NULL) //本身就是根节点
{
free(p);
(*root) = NULL;
}
else
{
//删除的结点是父节点的左孩子
if(p->parent->lchild == p)
p->parent->lchild = NULL;
//删除的结点是父节点的右孩子
if(p->parent->rchild == p)
p->parent->rchild = NULL;
free(p);
}
}
//2.被删结点只有左子树
else if(p->lchild && !(p->rchild))
{
p->lchild->parent = p->parent; //先改左孩子的parent指针
if(p->parent == NULL) //如果删除是根结点
(*root) = p->lchild; //左孩子升级成为根节点
//删除的结点是父节点的左孩子 //再改父亲节点的parent指针
else if(p->parent->lchild == p)
p->parent->lchild = p->lchild;
//删除的结点是父节点的右孩子
else if(p->parent->rchild == p)
p->parent->rchild = p->lchild;
free(p); //以免类存泄露
}
//3.被删结点只有右孩子
else if(p->rchild && !(p->lchild))
{
p->rchild->parent = p->parent;
if(p->parent == NULL)
(*root) = p->rchild;
//删除的结点是父节点的左孩子
else if(p->parent->lchild == p)
p->parent->lchild = p->rchild;
//删除的结点是父节点的右孩子
else if(p->parent->rchild == p)
p->parent->rchild = p->rchild;
free(p);
}
//4.被删除的结点既有左孩子,又有右孩子
//该结点的后继结点肯定无左子树(参考上面查找后继结点函数)
//删掉后继结点,后继结点的值代替该结点
else
{//找到要删除结点的后继
pnode q;
int tmp; //存后继结点的值
q = searchsuccessor(p);
tmp = q->key;
//删除后继结点
deletenode(root, tmp);
p->key = tmp;
}
return 1;
}

//创建二叉搜索树
void creatsearchtree(pnode *root, int *key, int length)
{

//逐个结点插入二叉树中
for(int i = 0; i < length; i++)
insert_node(root, key[i]); //root本身就是二级指针了,直接传root
}

int main()
{

pnode root = NULL; //这里的root是一级指针
int key[11] = {15,6,18,3,7,17,20,2,4,13,9};
creatsearchtree(&root, key, 11);
for(int i = 0; i < 2; i++)
deletenode(&root, key[i]);

printf("%d\n", searchpredecessor(root)->key);
printf("%d\n", searchsuccessor(root)->key);
printf("%d\n", searchmin(root)->key);
printf("%d\n", searchmax(root)->key);
printf("%d\n", searchnode(root, 13)->key);

printf("\n//////////////////////////////////\n");

int n ;
printf("Other search is same with searchnode, \nso I only display the search of searchnode \n");
while(scanf("%d", &n)!=EOF)
searchnode(root, n) ? printf("yes, the searchtree has %d\n", n) : printf("sorry ! Do have this node !\n");
return 0;
}
/*
例子 of deletenode函数
一:
O x
/ \
NULL NULL

O
/
O x
/ \
NULL NULL

O
\
O x
/ \
NULL NULL
二:
O x
/
O

O
/ \
x O O
/
O
/ \
O O

O
/ \
O O x
/
O
/ \
O O
三:

O x
\
O

O
/ \
x O O
\
O
/ \
O O

O
/ \
O O x
\
O
/ \
O O

*/

Contents