1 #define _CRT_SECURE_NO_WARNINGS
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <conio.h>
6
7 #define MAXLEN 20; //最大长度
8
9 typedef char DATA; //定义元素类型
10 typedef struct CBT //定义二叉树结点类型
11 {
12 DATA data; //元素数据
13 struct CBT *left; //左子树结点指针
14 struct CBT *right; //右子树结点指针
15 }CBTType;
16
17 CBTType *InitTree() //初始化二叉树的根
18 {
19 CBTType *node;
20
21 if(node=(CBTType *)malloc(sizeof(CBTType))) //申请内存
22 {
23 printf("请先输入一个根结点数据:\n");
24 scanf("%c",&node->data);
25 node->left = NULL;
26 node->right = NULL;
27
28 if(node!=NULL) //如果二叉树根结点不为空
29 {
30 return node;
31 }
32 else
33 {
34 return NULL;
35 }
36 return NULL;
37 }
38 }
39
40 CBTType *TreeFindNode(CBTType *treeNode, DATA data) //查找结点
41 {
42 CBTType *ptr;
43
44 if(treeNode == NULL)
45 {
46 return NULL;
47 }
48 else
49 {
50 if(treeNode->data == data)
51 {
52 return treeNode;
53 }
54 else
55 {
56 if(ptr=TreeFindNode(treeNode->left,data)) //分别向左右子树递归查找
57 {
58 return ptr;
59 }
60 else if(ptr=TreeFindNode(treeNode->right,data))
61 {
62 return ptr;
63 }
64 else
65 {
66 return NULL;
67 }
68 }
69 }
70 }
71
72 void AddTreeNode(CBTType *treeNode) //添加结点
73 {
74 CBTType *pnode, *parent;
75 DATA data;
76 char menusel;
77
78 if(pnode=(CBTType *)malloc(sizeof(CBTType))) //分配内存
79 {
80 printf("输入二叉树结点数据:\n");
81 fflush(stdin);
82 scanf("%c",&pnode->data);
83 pnode->left = NULL;
84 pnode->right = NULL; //设置左右子树为空
85
86 printf("请输入核结点父结点数据:");
87 fflush(stdin);
88 scanf("%c",&data);
89 parent = TreeFindNode(treeNode,data); //查找指定数据的结点
90 if(!parent) //如果未找到
91 {
92 printf("未找到该父结点!\n");
93 free(pnode); //释放创建的结点内存
94 return;
95 }
96 printf("1.添加该结点到左子树\n 2.添加该结点到右子树\n");
97 do
98 {
99 menusel = _getch(); //输入选择项
100 menusel -= '0';
101 if(menusel==1 || menusel==2)
102 {
103 if(parent==NULL)
104 {
105 printf("不存在父结点,请先设置父结点!\n");
106 }
107 else
108 {
109 switch (menusel)
110 {
111 case 1: //添加到左结点
112 if(parent->left) //左子树不为空
113 {
114 printf("左子树不为空!\n");
115 }
116 else
117 {
118 parent->left = pnode;
119 }
120 break;
121 case 2: //添加到右结点
122 if(parent->right) //右子树不为空
123 {
124 printf("右子树不为空!\n");
125 }
126 else
127 {
128 parent->right = pnode;
129 }
130 break;
131 default:
132 printf("无效参数!\n");
133 break;
134 }
135 }
136 }
137 }while(menusel != 1 && menusel != 2);
138 }
139 }
140
141 CBTType *TreeLeftNode(CBTType *treeNode) //获取左子树
142 {
143 if(treeNode)
144 {
145 return treeNode->left;
146 }
147 else
148 {
149 return NULL;
150 }
151 }
152
153 CBTType *TreeRightNode(CBTType *treeNode) //获取右子树
154 {
155 if(treeNode)
156 {
157 return treeNode->right;
158 }
159 else
160 {
161 return NULL;
162 }
163 }
164
165 int TreeIsEmpty(CBTType *treeNode) //判断空树
166 {
167 if(treeNode)
168 {
169 return 0;
170 }
171 else
172 {
173 return 1;
174 }
175 }
176
177 int TreeDepth(CBTType *treeNode) //计算二叉树的深度
178 {
179 int depleft, depright;
180
181 if(treeNode==NULL)
182 {
183 return 0; //对于空树,深度为0
184 }
185 else
186 {
187 depleft = TreeDepth(treeNode->left); //左子树深度(递归调用)
188 depright = TreeDepth(treeNode->right); //右子树深度(递归调用)
189 if(depleft>depright)
190 {
191 return depleft + 1;
192 }
193 else
194 {
195 return depright +1;
196 }
197 }
198 }
199
200 void ClearTree(CBTType *treeNode) //清空二叉树
201 {
202 if(treeNode)
203 {
204 ClearTree(treeNode->left); //清空左子树
205 ClearTree(treeNode->right); //清空右子树
206 free(treeNode); //释放当前结点所占内存
207 treeNode = NULL;
208 }
209 }
210
211 void TreeNodeData(CBTType *p) //显示结点数据
212 {
213 printf("%c",p->data); //输出结点数据
214 }
215
216 void DLRTree(CBTType *treeNode, void(*TreeNodeData)(CBTType *p)) //先序遍历
217 {
218 if(treeNode)
219 {
220 TreeNodeData(treeNode); //显示结点的数据
221 DLRTree(treeNode->left, TreeNodeData);
222 DLRTree(treeNode->right, TreeNodeData);
223 }
224 }
225
226 void LDRTree(CBTType *treeNode, void(*TreeNodeData)(CBTType *p)) //中序遍历
227 {
228 if(treeNode)
229 {
230 LDRTree(treeNode->left, TreeNodeData); //中序遍历左子树
231 TreeNodeData(treeNode); //显示结点数据
232 LDRTree(treeNode->right, TreeNodeData); //中序遍历右子树
233 }
234 }
235
236 void LRDTree(CBTType *treeNode, void(*TreeNodeData)(CBTType *p)) //后序遍历
237 {
238 if(treeNode)
239 {
240 LRDTree(treeNode->left, TreeNodeData); //后序遍历左子树
241 LRDTree(treeNode->right, TreeNodeData); //后序遍历右子树
242 TreeNodeData(treeNode); //显示结点数据
243 }
244 }
245
246 void main()
247 {
248 CBTType *root = NULL; //root为指向二叉树根结点的指针
249 char menusel;
250 void(*TreeNodeData1)(CBTType *p); //指向函数的指针
251 TreeNodeData1 = TreeNodeData; //指向具体操作的函数
252 //设置根元素
253 root = InitTree();
254 //添加结点
255 do
256 {
257 printf("请选择菜单添加二叉树的结点\n");
258 printf("0.退出\t"); //显示菜单
259 printf("1.添加二叉树的结点\n");
260 menusel = _getch();
261 switch (menusel)
262 {
263 case '1': //添加结点
264 AddTreeNode(root);
265 break;
266 case '0':
267 break;
268 default:
269 break;
270 }
271 }while(menusel!='0');
272
273 //遍历
274 do
275 {
276 printf("请选择菜单遍历二叉树,输入0表示退出:\n");
277 printf("1.先序遍历DLR\t"); //显示菜单
278 printf("2.中序遍历LDR\n");
279 printf("3.后序遍历LRD\t");
280 menusel=_getch();
281 switch (menusel)
282 {
283 case '0':
284 break;
285 case '1': //先序遍历
286 printf("\n先序遍历DLR的结果: ");
287 DLRTree(root,TreeNodeData1);
288 printf("\n");
289 break;
290 case '2': //中序遍历
291 printf("\n中序遍历的结果:");
292 LDRTree(root, TreeNodeData1);
293 printf("\n");
294 break;
295 case '3': //后序遍历
296 printf("\n后序遍历LRD的结果:");
297 LRDTree(root,TreeNodeData1);
298 printf("\n");
299 break;
300 default:
301 break;
302 }
303 }while(menusel != '0');
304
305 //深度
306 printf("\n二叉树深度为:%d\n",TreeDepth(root));
307
308 ClearTree(root); //清空二叉树
309 root = NULL;
310 }