二叉树的一些基本操作

  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 << '	';
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 << '	';
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 << '	';
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 }
原文地址:https://www.cnblogs.com/ReturnOfTheKing/p/11233459.html