• 二叉树的一些基本操作


      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 }
  • 相关阅读:
    几个前端时间插件总结
    微信支付——退款篇
    getTime()方法在苹果系统的bug
    【转载】[JS]让表单提交返回后保持在原来提交的位置上
    【转载】 IE/Firefox每次刷新时自动检查网页更新,无需手动清空缓存的设置方法
    webstorm相关设置
    检测无标题的
    数组去重的方法
    Git 版本比较
    Git 回到过去
  • 原文地址:https://www.cnblogs.com/ReturnOfTheKing/p/11233459.html
Copyright © 2020-2023  润新知