1 #ifndef BITREE_H_INCLUDED
2 #define BITREE_H_INCLUDED
3
4 /************************************************
5 *文件名: BiTree.h
6 *创建人: 水龙头
7 *日 期: 2019.7.22
8 *描 述: 二叉树的基本操作
9 ***********************************************/
10 #define OK 1
11 #define ERROR -1
12 #define TRUE 1
13 #define FALSE 0
14 #define OVERFLOW -2
15 #define INFEASIBLE -1
16 typedef char TElemType;
17 typedef int Status;
18 //二叉树节点类型
19 typedef struct BiTNode
20 {
21 TElemType data;
22 int flag; //标志域,为了方便后序遍历的进行
23 struct BiTNode *lchild, *rchild;
24
25 }BiTNode, *BiTree;
26 //构造空二叉树
27 Status InitBiTree(BiTree&);
28 //创建一棵二叉树
29 Status CreateBiTree(BiTree&);
30 //先序遍历
31 Status PreOrderTraverse(const BiTree&, Status (*visit)(const BiTree&));
32 //中序遍历
33 Status InOrderTraverse(const BiTree&, Status (*visit)(const BiTree&));
34 //后序遍历
35 Status PostOrderTraverse(const BiTree&, Status (*visit)(const BiTree&));
36 //层次遍历
37 Status LevelOrderTraverse(const BiTree&, Status (*visit)(const BiTree&));
38 //销毁一颗二叉树
39 Status DestroyBiTree(BiTree&);
40 //清空一棵二叉树
41 Status ClearBiTree(BiTree&);
42 //判断一颗二叉树是否为空
43 Status BiTreeEmpty(const BiTree&);
44 //求二叉树的深度
45 Status BiTreeDepth(const BiTree&);
46 //插入一个节点
47 Status InsertChild(BiTree&);
48 //删除一个节点
49 Status DeleteChild(BiTree&);
50 //查找节点所在处
51 BiTree Location(const BiTree&, TElemType, Status (*compare)(BiTree, TElemType));
52 //访问节点
53 Status Visit(const BiTree&);
54 //比较两关键字是否相等
55 Status Compare(BiTree, TElemType);
56
57 #endif // BITREE_H_INCLUDED
58
59
60
61
62 /************************************************
63 *文件名: BiTree.cpp
64 *创建人: 水龙头
65 *日 期: 2019.7.22
66 *描 述: 二叉树的基本操作
67 ***********************************************/
68 #include <iostream>
69 #include "BiTree.h"
70 #include "Stack.h"
71 #include "Queue.h"
72 //注意将各个头文件保持一致
73 using namespace std;
74 //构造空二叉树
75 Status InitBiTree(BiTree& T)
76 {
77 T = NULL;
78 return OK;
79 }
80 //创建一棵二叉树(先序递归创建)
81 Status CreateBiTree(BiTree& T)
82 {
83 //节点数据
84 TElemType ch;
85 cin >> ch;
86 if(ch == '@')
87 {
88 T = NULL;
89 return OK;
90 }
91 else
92 {
93 T = new BiTNode;
94 if(T)
95 {
96 T->data = ch;
97 CreateBiTree(T->lchild);
98 CreateBiTree(T->rchild);
99 return OK;
100 }
101 else
102 {
103 //节点创建失败,导致直接退出程序
104 exit(-1);
105 }
106 }
107 }
108 //先序遍历
109 Status PreOrderTraverse(const BiTree& T, Status (*visit)(const BiTree&))
110 {
111 //先序遍历的总体思路:
112 //如果左儿子存在,则将其压入栈中;如果左儿子不存在,则将栈顶元素弹出,并令指针指向其右儿子。
113 //在节点压入栈中之前就要将其访问掉。
114 BiTree ptr = T, p = NULL;
115 if(ptr)
116 {
117 //格式需要
118 cout << "先序遍历的结果为: ";
119 if(visit(ptr))
120 {
121 //因为需要将指针压入栈中,所以需要使栈中的元素类型与指针类型保持一致
122 LinkList top = NULL;
123 Init_Stack(top);
124 Push(top, ptr);
125 ptr = ptr->lchild;
126 while(ptr || !StackEmpty(top))
127 {
128 //如果左儿子存在
129 if(ptr)
130 {
131 if(visit(ptr))
132 {
133 Push(top, ptr);
134 ptr = ptr->lchild;
135 }
136 //访问失败
137 else
138 return ERROR;
139 }
140 else if(!ptr)
141 {
142 Pop(top, p);
143 ptr = p->rchild;
144 }
145
146 }
147 }
148 else
149 return ERROR;
150 }
151 //格式需要
152 cout << endl;
153 return OK;
154 }
155 //中序遍历
156 Status InOrderTraverse(const BiTree& T, Status (*visit)(const BiTree&))
157 {
158 //中序遍历的总体思路:
159 //仔细观察会发现,其实先序遍历与中序遍历走的路线是完全一样的,唯一的区别在于节点的访问时机。
160 //在节点弹出时再对其进行访问。
161 BiTree ptr = T, p = NULL;
162 if(ptr)
163 {
164 //格式需要
165 cout << "先序遍历的结果为: ";
166 LinkList top = NULL;
167 Init_Stack(top);
168 Push(top, ptr);
169 ptr = ptr->lchild;
170 while(ptr || !StackEmpty(top))
171 {
172 if(ptr)
173 {
174 Push(top, ptr);
175 ptr = ptr->lchild;
176 }
177 else if(!ptr)
178 {
179 Pop(top, p);
180 if(visit(p))
181 {
182 ptr = p->rchild;
183 }
184 //访问失败
185 else
186 {
187 return ERROR;
188 }
189 }
190 }
191 }
192 //格式需要
193 cout << endl;
194 return OK;
195 }
196 //后序遍历
197 Status PostOrderTraverse(const BiTree& T, Status (*visit)(const BiTree&))
198 {
199 //后序遍历的思路:
200 //先对于先序与中序来说,后序的路线更为复杂。
201 //多了一个标志域;只有当该节点已经进入过栈中两次后才可以对其进行访问。
202 BiTree ptr = T, p = NULL;
203 if(ptr)
204 {
205 //格式需要
206 cout << "先序遍历的结果为: ";
207 LinkList top = NULL;
208 Init_Stack(top);
209 //表示该节点第一次被压入栈中
210 ptr->flag = 1;
211 Push(top, ptr);
212 ptr = ptr->lchild;
213 while(ptr || !StackEmpty(top))
214 {
215 if(ptr)
216 {
217 ptr->flag = 1;
218 Push(top, ptr);
219 ptr = ptr->lchild;
220 }
221 else if(!ptr)
222 {
223 Pop(top, p);
224 if(p->flag == 1)
225 {
226 //表示该节点第二次入栈
227 p->flag = 2;
228 Push(top, p);
229 ptr = p->rchild;
230 }
231 //该节点已经进入过栈中两次
232 else
233 {
234 if(visit(p))
235 {
236 //为了让下一次进入循环就直接出栈
237 ptr = NULL;
238 }
239 else
240 return ERROR;
241 }
242 }
243 }
244
245 }
246 //格式需要
247 cout << endl;
248 return OK;
249 }
250 //层次遍历
251 Status LevelOrderTraverse(const BiTree& T, Status (*visit)(const BiTree&))
252 {
253 //层次遍历的思路:
254 //从上到下、从左到右.
255 //一个节点要在其左右儿子(如果存在的话)都进入队列后,再出队列并立即对其进行访问.
256 BiTree ptr = T;
257 QueuePtr q = NULL;
258 if(ptr)
259 {
260 //格式需要
261 cout << "层次遍历的结果为: ";
262 LinkQueue Q;
263 InitQueue(Q);
264 EnQueue(Q, ptr);
265 while(!QueueEmpty(Q))
266 {
267 //得到队首元素
268 //因为所使用的队列头文件GetHead函数参数类型有点冲突,所以此处需要拆一下包装。
269 //注意q的类型
270 GetHead(Q, q);
271 //如果队首的左儿子存在则入队列
272 if(q->Qdata->lchild)
273 {
274 EnQueue(Q, q->Qdata->lchild);
275 }
276 //如果ptr的右儿子存在则入队列
277 if(q->Qdata->rchild)
278 {
279 EnQueue(Q, q->Qdata->rchild);
280 }
281 //然后再删除队首元素并对其进行访问
282 DeQueue(Q, q->Qdata);
283 if(!visit(q->Qdata))
284 {
285 //访问失败
286 return ERROR;
287 }
288 }
289 }
290 //格式需要
291 cout << endl;
292 return OK;
293 }
294 //销毁(清空)一颗(链式)二叉树
295 Status DestroyBiTree(BiTree& T)
296 {
297 if(T)
298 {
299 DestroyBiTree(T->lchild);
300 DestroyBiTree(T->rchild);
301 T = NULL;
302 }
303 return OK;
304 }
305 //判断一颗二叉树是否为空
306 Status BiTreeEmpty(const BiTree& T)
307 {
308 if(T)
309 {
310 return ERROR;
311 }
312 else
313 return TRUE;
314 }
315 //求二叉树的深度
316 Status BiTreeDepth(const BiTree& T)
317 {
318 int Depth = 0, LeftDepth = 0, RigthDepth = 0;
319 if(T)
320 {
321 LeftDepth = BiTreeDepth(T->lchild);
322 RigthDepth = BiTreeDepth(T->rchild);
323 Depth = 1 + (LeftDepth > RigthDepth ? LeftDepth : RigthDepth);
324 return Depth;
325 }
326 return 0;
327 }
328 //访问节点
329 Status Visit(const BiTree& p)
330 {
331 if(p)
332 {
333 cout << p->data << '\t';
334 return OK;
335 }
336 else
337 return ERROR;
338 }
339 //比较两关键字是否相等
340 Status Compare(BiTree ptr1, TElemType ptr2)
341 {
342 if(ptr1->data == ptr2)
343 return TRUE;
344 else
345 return 0;
346 }
347 //查找节点所在处
348 BiTree Location(const BiTree& T, TElemType e, Status (*compare)(BiTree, TElemType))
349 {
350 //模仿了一下层次遍历
351 BiTree ptr = T;
352 QueuePtr q = NULL;
353 if(ptr)
354 {
355 LinkQueue Q;
356 InitQueue(Q);
357 EnQueue(Q, ptr);
358 while(!QueueEmpty(Q))
359 {
360 //得到队首元素
361 //因为所使用的队列头文件GetHead函数参数类型有点冲突,所以此处需要拆一下包装。
362 //注意q的类型
363 GetHead(Q, q);
364 //如果队首的左儿子存在则入队列
365 if(q->Qdata->lchild)
366 {
367 EnQueue(Q, q->Qdata->lchild);
368 }
369 //如果ptr的右儿子存在则入队列
370 if(q->Qdata->rchild)
371 {
372 EnQueue(Q, q->Qdata->rchild);
373 }
374 //然后再删除队首元素并对其进行访问
375 DeQueue(Q, q->Qdata);
376 if(compare(q->Qdata, e))
377 {
378 return (q->Qdata);
379 }
380 }
381 }
382 return NULL;
383 }
384
385
386
387 /************************************************
388 *文件名: Stack.h
389 *创建人: 水龙头
390 *日 期: 2019.7.20
391 *描 述: 链式栈(带表头)
392 ***********************************************/
393 #ifndef STACK_H_INCLUDED
394 #define STACK_H_INCLUDED
395
396
397
398 #include<iostream>
399 #include "BiTree.h"
400 using namespace std;
401 #define TRUE 1
402 #define FALSE 0
403 #define ERROR -1
404 #define OK 1
405 #define OVERFLOW -2
406 #define INFEASIBLE -1
407 typedef BiTree SElemType;
408 typedef int Status;
409 typedef struct SNode
410 {
411 SElemType data;
412 struct SNode *next;
413 }SNode, *LinkList;
414 Status Init_Stack(LinkList &top);
415 Status Push(LinkList &top, SElemType ch);
416 Status Pop(LinkList &top, SElemType &e);
417 Status GetTop(const LinkList &top, SElemType &e);
418 Status DestroyStack(LinkList&);
419 Status ClearStack(LinkList&);
420 Status StackEmpty(const LinkList&);
421 Status StackLength(const LinkList&);
422 Status StackTraverse(const LinkList& , Status (*visit)(const LinkList&));
423 Status Visit(const LinkList&);
424
425 #endif // STACK_H_INCLUDED
426
427
428
429
430 /************************************************
431 *文件名: Stack.cpp
432 *创建人: 水龙头
433 *日 期: 2019.7.20
434 *描 述: 链式栈(带表头)
435 ***********************************************/
436 #include "Stack.h"
437 Status GetTop(const LinkList &top, SElemType &e) //得到栈顶元素
438 {
439 if(top)
440 {
441 LinkList p = top;
442 if(!p->next)
443 {
444 return ERROR;
445 }
446 else
447 {
448 e = top->data;
449 return OK;
450 }
451 }
452 else
453 {
454 return INFEASIBLE;
455 }
456 }
457 Status DestroyStack(LinkList& top)
458 {
459 LinkList ptr = NULL;
460 while(top)
461 {
462 ptr = top;
463 top = top->next;
464 free(ptr);
465 }
466 return OK;
467 }
468 Status ClearStack(LinkList& top)
469 {
470 if(top)
471 {
472 LinkList ptr = NULL;
473 while(top->next)
474 {
475 ptr = top;
476 top = top->next;
477 free(ptr);
478 }
479 return OK;
480 }
481 else
482 return INFEASIBLE;
483 }
484 Status StackEmpty(const LinkList& top)
485 {
486 if(top)
487 {
488 if(top->next)
489 {
490 return FALSE;
491 }
492 else
493 return TRUE;
494 }
495 else
496 return INFEASIBLE;
497 }
498 Status StackLength(const LinkList& top)
499 {
500 if(top)
501 {
502 int count = 0;
503 LinkList ptr = top;
504 while(ptr->next)
505 {
506 ptr = ptr->next;
507 count++;
508 }
509 return count;
510 }
511 else
512 return INFEASIBLE;
513 }
514 Status StackTraverse(const LinkList& top, Status (*visit)(const LinkList&))
515 {
516 if(top)
517 {
518 LinkList ptr = top;
519 while(ptr->next)
520 {
521 visit(ptr);
522 ptr = ptr->next;
523 }
524 return OK;
525 }
526 else
527 return INFEASIBLE;
528 }
529 Status Visit(const LinkList& ptr)
530 {
531 cout << ptr->data << '\t';
532 return OK;
533 }
534 Status Init_Stack(LinkList &top) //初始化栈
535 {
536 LinkList p = (SNode *)malloc(sizeof(SNode));
537 if(!p)
538 {
539 return OVERFLOW;
540 }
541 else
542 {
543 p->next = NULL;
544 top = p;
545 return OK;
546 }
547 }
548 Status Push(LinkList &top, SElemType ch)
549 {
550 if(top)
551 {
552 LinkList q = (SNode *)malloc(sizeof(SNode));
553 if(!q)
554 {
555 return OVERFLOW;
556 }
557 else
558 {
559 q->next = top; //注意这一步是将头指针赋给新节点的后继
560 q->data = ch;
561 top = q;
562 return OK;
563 }
564 }
565 else
566 return INFEASIBLE;
567 }
568 Status Pop(LinkList &top,SElemType&e) //不能对字面值进行引用
569 {
570 if(top)
571 {
572 LinkList p = top;
573 if(!p->next)
574 {
575 return ERROR;
576 }
577 else
578 {
579 e = top->data;
580 top = top->next;
581 free(p);
582 return OK;
583 }
584 }
585 else
586 return INFEASIBLE;
587 }
588
589
590
591
592 /************************************************
593 *文件名: Queue.h
594 *创建人: 水龙头
595 *日 期: 2019.7.14
596 *描 述: 链式队列
597 ***********************************************/
598 #ifndef QUEUE_H_INCLUDED
599 #define QUEUE_H_INCLUDED
600
601
602 #include <iostream>
603 #include "BiTree.h"
604 using namespace std;
605 #define TRUE 1
606 #define FALSE 0
607 #define OK 1
608 #define ERROR -1
609 #define OVERFLOW -2
610
611 typedef BiTree QElemType;
612 typedef int Status;
613 typedef struct QNode
614 {
615 QElemType Qdata;
616 struct QNode* next;
617 }QNode, *QueuePtr;
618 typedef struct
619 {
620 QueuePtr front; //队首指针
621 QueuePtr rear; //队尾指针
622 }LinkQueue;
623 Status InitQueue(LinkQueue&); //初始化队列
624 Status DestroyQueue(LinkQueue&); //销毁队列
625 Status ClearQueue(LinkQueue&); //清空队列
626 Status QueueEmpty(const LinkQueue&); //判断队列是否为空
627 int QueueLength(const LinkQueue&); //返回队列长度
628 Status GetHead(const LinkQueue&, QueuePtr&); //返回队首元素
629 Status EnQueue(LinkQueue&, QElemType); //插入一个元素
630 Status DeQueue(LinkQueue&, QElemType&); //删除一个元素
631 Status QueueTraverse(const LinkQueue&, Status (*visit)(const QueuePtr )); //遍历整个队列
632 Status Visit(const QueuePtr);
633
634
635
636 #endif // QUEUE_H_INCLUDED
637
638
639
640
641 /************************************************
642 *文件名:Queue.cpp
643 *创建人:水龙头
644 *日 期: 2019.7.14
645 *描 述: 链式队列
646 ***********************************************/
647 #include "Queue.h"
648
649 Status InitQueue(LinkQueue& Q)
650 {
651 Q.front = Q.rear = new QNode; //带头节点的链式队列
652 if(Q.front)
653 {
654 Q.front->next = NULL;
655 return OK;
656 }
657 else
658 return OVERFLOW;
659 }
660 Status DestroyQueue(LinkQueue& Q)
661 {
662 while(Q.front)
663 {
664 Q.rear = Q.front->next;
665 delete (Q.front); //空间虽已销毁,但原本指向该空间的指针还在,只不过变为野指针了而已。
666 Q.front = Q.rear;
667 }
668 return OK;
669 }
670 Status ClearQueue(LinkQueue& Q)
671 {
672 QueuePtr ptr = Q.front->next;
673 Q.rear = Q.front;
674 while(ptr)
675 {
676 QueuePtr p = ptr;
677 ptr = ptr->next;
678 delete p;
679 }
680 return OK;
681 }
682 Status QueueEmpty(const LinkQueue& Q)
683 {
684 if(Q.front == Q.rear)
685 return TRUE;
686 else
687 return FALSE;
688 }
689 int QueueLength(const LinkQueue& Q)
690 {
691 if(Q.front == Q.rear)
692 return 0;
693 else
694 {
695 int count = 0;
696 QueuePtr ptr = Q.front->next;
697 while(ptr)
698 {
699 count++;
700 ptr = ptr->next;
701 }
702 return count;
703 }
704 }
705 Status GetHead(const LinkQueue& Q, QueuePtr& ptr)
706 {
707 QueuePtr p = Q.front->next;
708 if(p)
709 {
710 ptr = p;
711 return OK;
712 }
713 else
714 {
715 ptr = NULL;
716 return ERROR;
717 }
718 }
719 Status EnQueue(LinkQueue& Q, QElemType e)
720 {
721 QueuePtr ptr = new QNode;
722 if(ptr)
723 {
724 ptr->next = NULL;
725 ptr->Qdata = e;
726 Q.rear->next = ptr;
727 Q.rear = ptr;
728 return OK;
729 }
730 else
731 return OVERFLOW;
732 }
733 Status DeQueue(LinkQueue& Q, QElemType& e)
734 {
735 if(Q.front == Q.rear)
736 return ERROR;
737 else //注意这是队列,只能从队首删除元素,从队尾插入元素
738 {
739 QueuePtr ptr = Q.front->next;
740 Q.front->next = ptr->next;
741 e = ptr->Qdata;
742 if(ptr == Q.rear) //如果原本队列里只有一个元素
743 {
744 Q.rear = Q.front;
745 }
746 delete ptr;
747 return OK;
748 }
749 }
750 Status Visit(const QueuePtr ptr)
751 {
752 if(!ptr)
753 {
754 return ERROR;
755 }
756 else
757 {
758 cout << ptr->Qdata << '\t';
759 return OK;
760 }
761 }
762 Status QueueTraverse(const LinkQueue& Q, Status (*visit)(const QueuePtr ))
763 {
764 QueuePtr ptr = NULL;
765 if(Q.front == Q.rear)
766 return ERROR;
767 else
768 {
769 ptr = Q.front->next; //从第一个节点开始遍历(带头节点的链表)
770 while(ptr)
771 {
772 (*visit)(ptr);
773 ptr = ptr->next;
774 }
775 cout << endl;
776 return OK;
777 }
778 }