• C++ 二叉树遍历实现


    1. 原文:http://blog.csdn.net/nuaazdh/article/details/7032226
    2. //二叉树遍历  
    3. //作者:nuaazdh  
    4. //时间:2011年12月1日  
    5.   
    6. #include<stdio.h>  
    7. #include<stdlib.h>  
    8.   
    9. //二叉树结点结构  
    10. typedef struct BiTNode{  
    11.     char ch;            //结点数据  
    12.     struct BiTNode *lchild;        //左孩子  
    13.     struct BiTNode *rchild;        //右孩子  
    14. }BiTNode,*BiTree;  
    15.   
    16.   
    17. void AddBiTree(BiTree ,BiTNode *);//创建二叉树  
    18. void PreOrderTraverse(BiTNode *); //前序遍历  
    19. void InOrderTraverse(BiTNode *);   //中序遍历  
    20. void PostOrderTraverse(BiTNode *);  //后序遍历  
    21.   
    22.   
    23. void main()  
    24. {  
    25.     char ch;//结点数据  
    26.     BiTree T,p;//树T,和临时树p  
    27.     printf("请输入结点内容(以空格未结束标识):");  
    28.     scanf("%c",&ch);//读入用户输入  
    29.     T=NULL;  
    30.   
    31.     while(ch!=' '){//判断输入  
    32.         //创建新结点  
    33.         if(p=(BiTNode *)malloc(sizeof(BiTNode))){  
    34.             p->ch = ch;  
    35.             p->lchild = NULL;  
    36.             p->rchild = NULL;  
    37.         }  
    38.         else  
    39.         {  
    40.             printf("内存分配出错. ");  
    41.             exit(0);  
    42.         }  
    43.         if(T==NULL)  
    44.             T=p;  
    45.         else  
    46.             AddBiTree(T,p);  
    47.         scanf("%c",&ch);//读入用户输入  
    48.     }  
    49.     //输出遍历结果  
    50.     printf("前序遍历: ");  
    51.     PreOrderTraverse(T);  
    52.     printf(" 中序遍历: ");  
    53.     InOrderTraverse(T);  
    54.     printf(" 后序遍历: ");  
    55.     PostOrderTraverse(T);  
    56. }  
    57.   
    58.   
    59. //创造二叉树  
    60. void AddBiTree(BiTree T,BiTree p)  
    61. {  
    62.     if((p->ch <= T->ch)&&(T->lchild!=NULL))  
    63.         AddBiTree(T->lchild,p);  
    64.     else if((p->ch <= T->ch)&&(T->lchild==NULL))  
    65.         T->lchild=p;  
    66.     else if(T->rchild!=NULL)  
    67.         AddBiTree(T->rchild,p);  
    68.     else T->rchild=p;  
    69. }  
    70.   
    71.   
    72. //前序遍历  
    73. void PreOrderTraverse(BiTree T)  
    74. {  
    75.     if(T){  
    76.         printf("%c ",T->ch);  
    77.         PreOrderTraverse(T->lchild);  
    78.         PreOrderTraverse(T->rchild);  
    79.     }  
    80. }  
    81.   
    82. //中序遍历  
    83. void InOrderTraverse(BiTree T)  
    84. {  
    85.     if(T){  
    86.         InOrderTraverse(T->lchild);  
    87.         printf("%c ",T->ch);  
    88.         InOrderTraverse(T->rchild);  
    89.     }  
    90. }  
    91.   
    92. //后序遍历  
    93. void PostOrderTraverse(BiTree T)  
    94. {  
    95.     if(T){  
    96.         PostOrderTraverse(T->lchild);  
    97.         PostOrderTraverse(T->rchild);  
    98.         printf("%c ",T->ch);  
    99.     }  
    100. }

    原文:http://blog.csdn.net/oohaha_123/article/details/25902697

    二叉树的非递归遍历

    最近看书上说道要掌握二叉树遍历的6种编写方式,之前只用递归方式编写过,这次就用非递归方式编写试一试。

    C++编程练习(8)----“二叉树的建立以及二叉树的三种遍历方式“(前序遍历、中序遍历、后续遍历)

    递归的思想也就是栈的思想,既然不用递归,那就改用栈的方式。

    “递归=栈”

    1、前序遍历

    前序遍历按照“根结点-左孩子-右孩子”的顺序进行访问。

    a)递归实现前序遍历:

    [cpp] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. void PreOrderTraverse(BiTNode *T)   /*递归前序遍历*/  
    2. {  
    3.     if (T==NULL)  
    4.         return;  
    5.     std::cout<<T->data<<" ";  
    6.     PreOrderTraverse(T->lchild);  
    7.     PreOrderTraverse(T->rchild);  
    8. }  

    b)非递归实现前序遍历:

    对于根结点P:
    1)访问结点P,并将结点P入栈;
    2)判断结点P的左孩子是否为空,若为空,则取栈顶结点并进行出栈操作,并将栈顶结点的右孩子置为当前的结点P,循环至1);若不为空,则将P的左孩子置为当前的结点P;
    3)直到P为NULL并且栈为空,则遍历结束。

    [cpp] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. void nPreOrderTraverse(BiTNode *T)  /*非递归前序遍历*/  
    2. {  
    3.     if (T==NULL)  
    4.         return;  
    5.     BiTNode *p;  
    6.     p = T;  
    7.     std::stack<BiTNode*> stk;  
    8.     while(p!=NULL||!stk.empty())  
    9.     {  
    10.         while(p!=NULL)  
    11.         {  
    12.             std::cout<<p->data<<" ";  
    13.             stk.push(p);  
    14.             p = p->lchild;  
    15.         }  
    16.         if(!stk.empty())  
    17.         {  
    18.             p = stk.top();  
    19.             stk.pop();  
    20.             p = p->rchild;  
    21.         }  
    22.     }     
    23. }  

    2、中序遍历

    中序遍历按照“左孩子-根结点-右孩子”的顺序进行访问。

    a)递归实现中序遍历

    [cpp] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. void InOrderTraverse(BiTNode *T)    /*递归中序遍历*/  
    2. {  
    3.     if (T==NULL)  
    4.         return;  
    5.     InOrderTraverse(T->lchild);  
    6.     std::cout<<T->data<<" ";  
    7.     InOrderTraverse(T->rchild);  
    8. }  

    b)非递归实现中序遍历

    对于根结点P:
    1)若其左孩子不为空,则将P入栈并将P的左孩子置为当前的P,然后对当前结点P再进行相同的处理;
    2)若其左孩子为空,则取栈顶元素并进行出栈操作,访问该栈顶结点,然后将当前的P置为栈顶结点的右孩子;
    3)直到P为NULL并且栈为空则遍历结束。

    [cpp] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. void nInOrderTraverse(BiTNode *T)   /*非递归中序遍历*/  
    2. {  
    3.     if(T==NULL)  
    4.         return;  
    5.     std::stack<BiTNode*> stk;  
    6.     BiTNode* p;  
    7.     p = T;  
    8.     while(p!=NULL || !stk.empty())  
    9.     {  
    10.         while(p!=NULL)  
    11.         {  
    12.             stk.push(p);  
    13.             p = p->lchild;  
    14.         }  
    15.         if(!stk.empty())  
    16.         {  
    17.             p = stk.top();  
    18.             stk.pop();  
    19.             std::cout<<p->data<<" ";  
    20.             p = p->rchild;  
    21.         }  
    22.     }  
    23. }  

    3、后序遍历

    后序遍历按照“左孩子-右孩子-根结点”的顺序进行访问。

    a)递归实现后序遍历

    [cpp] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. void PostOrderTraverse(BiTNode *T)  /*递归后序遍历*/  
    2. {  
    3.     if(T==NULL)  
    4.             return;  
    5.     PostOrderTraverse(T->lchild);  
    6.     PostOrderTraverse(T->rchild);  
    7.     std::cout<<T->data<<" ";  
    8. }  

    b)非递归实现后序遍历

    这里实现略复杂,当初想出来的方法过于笨重,后参考http://www.cnblogs.com/dolphin0520/archive/2011/08/25/2153720.html,改写如下:

    要保证根结点在左孩子和右孩子访问之后才能访问,因此对于任一结点P,先将其入栈。如果P不存在左孩子和右孩子,则可以直接访问它;或者P存在左孩子或者右孩子,但是其左孩子和右孩子都已被访问过了,则同样可以直接访问该结点。若非上述两种情况,则将P的右孩子和左孩子依次入栈,这样就保证了每次取栈顶元素的时候,左孩子在右孩子前面被访问,左孩子和右孩子都在根结点前面被访问。

    对于根结点P:

    1)将P入栈,设置当前结点 cur ;

    2)将当前的 cur 置为栈顶结点,如果 cur 不存在左孩子和右孩子,或者 cur 存在左孩子或者右孩子,但是其左孩子和右孩子都已被访问过了,则可以直接访问该结点并进行出栈操作。否则将 cur 的右孩子和左孩子依次入栈;

    3)直到栈为空则遍历结束。

    [cpp] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. void nPostOrderTraverse(BiTNode *T)     /*非递归后序遍历*/  
    2. {  
    3.     if(T==NULL)  
    4.         return;  
    5.     BiTNode* cur;       /*当前结点*/  
    6.     BiTNode* pre = NULL;        /*前一次输出的结点*/  
    7.     std::stack<BiTNode*> stk;  
    8.     stk.push(T);  
    9.     while(!stk.empty())  
    10.     {  
    11.         cur = stk.top();  
    12.         if((cur->lchild==NULL && cur->rchild==NULL) ||  
    13.             (pre!=NULL && (cur->lchild==pre || cur->rchild==pre)))      
    14.         {                               /*如果当前结点没有孩子结点或者孩子节点都已被访问过*/  
    15.             std::cout<<cur->data<<" ";  
    16.             stk.pop();  
    17.             pre = cur;  
    18.         }  
    19.         else  
    20.         {  
    21.             if(cur->rchild!=NULL)  
    22.                 stk.push(cur->rchild);  
    23.             if(cur->lchild!=NULL)  
    24.                 stk.push(cur->lchild);  
    25.         }  
    26.     }  
    27. }  

    4、完整测试代码

    1)BiTree.h头文件

    [cpp] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. /* BiTree.h头文件 */  
    2. #include<iostream>  
    3. #include<stack>  
    4. typedef char TElemType;  
    5.   
    6. class BiTNode{                  /*创建结点类,使用的是左右孩子表示法*/  
    7. public:  
    8.     BiTNode():data(0),lchild(NULL),rchild(NULL){}  
    9.     TElemType data;  
    10.     BiTNode *lchild,*rchild;  
    11. };  
    12.   
    13. void CreateBiTree(BiTNode **T)      /*二叉树的建立,这里形参用的是双指针,需要注意*/  
    14. {                                           /*这里输入的是一个扩展二叉树,每个结点若有空指针,*/  
    15.     TElemType ch;                               /*则将其值设为一个特定值,本代码中是'#'*/  
    16.     std::cin>>ch;  
    17.     std::cin.clear();  
    18.     if(ch=='#')  
    19.         *T=NULL;  
    20.     else  
    21.     {  
    22.         *T=new BiTNode;  
    23.         if(!*T)  
    24.             exit(1);  
    25.         (*T)->data=ch;  
    26.         CreateBiTree(&(*T)->lchild);  
    27.         CreateBiTree(&(*T)->rchild);  
    28.     }  
    29. }  
    30.   
    31. void PreOrderTraverse(BiTNode *T)   /*递归前序遍历*/  
    32. {  
    33.     if (T==NULL)  
    34.         return;  
    35.     std::cout<<T->data<<" ";  
    36.     PreOrderTraverse(T->lchild);  
    37.     PreOrderTraverse(T->rchild);  
    38. }  
    39.   
    40. void nPreOrderTraverse(BiTNode *T)  /*非递归前序遍历*/  
    41. {  
    42.     if (T==NULL)  
    43.         return;  
    44.     BiTNode *p;  
    45.     p = T;  
    46.     std::stack<BiTNode*> stk;  
    47.     while(p!=NULL||!stk.empty())  
    48.     {  
    49.         while(p!=NULL)  
    50.         {  
    51.             std::cout<<p->data<<" ";  
    52.             stk.push(p);  
    53.             p = p->lchild;  
    54.         }  
    55.         if(!stk.empty())  
    56.         {  
    57.             p = stk.top();  
    58.             stk.pop();  
    59.             p = p->rchild;  
    60.         }  
    61.     }     
    62. }  
    63.   
    64.   
    65. void InOrderTraverse(BiTNode *T)    /*递归中序遍历*/  
    66. {  
    67.     if (T==NULL)  
    68.         return;  
    69.     InOrderTraverse(T->lchild);  
    70.     std::cout<<T->data<<" ";  
    71.     InOrderTraverse(T->rchild);  
    72. }  
    73.   
    74. void nInOrderTraverse(BiTNode *T)   /*非递归中序遍历*/  
    75. {  
    76.     if(T==NULL)  
    77.         return;  
    78.     std::stack<BiTNode*> stk;  
    79.     BiTNode* p;  
    80.     p = T;  
    81.     while(p!=NULL || !stk.empty())  
    82.     {  
    83.         while(p!=NULL)  
    84.         {  
    85.             stk.push(p);  
    86.             p = p->lchild;  
    87.         }  
    88.         if(!stk.empty())  
    89.         {  
    90.             p = stk.top();  
    91.             stk.pop();  
    92.             std::cout<<p->data<<" ";  
    93.             p = p->rchild;  
    94.         }  
    95.     }  
    96. }  
    97.   
    98. void PostOrderTraverse(BiTNode *T)  /*递归后序遍历*/  
    99. {  
    100.     if(T==NULL)  
    101.             return;  
    102.     PostOrderTraverse(T->lchild);  
    103.     PostOrderTraverse(T->rchild);  
    104.     std::cout<<T->data<<" ";  
    105. }  
    106.   
    107. void nPostOrderTraverse(BiTNode *T)     /*非递归后序遍历*/  
    108. {  
    109.     if(T==NULL)  
    110.         return;  
    111.     BiTNode* cur;       /*当前结点*/  
    112.     BiTNode* pre = NULL;        /*前一次输出的结点*/  
    113.     std::stack<BiTNode*> stk;  
    114.     stk.push(T);  
    115.     while(!stk.empty())  
    116.     {  
    117.         cur = stk.top();  
    118.         if((cur->lchild==NULL && cur->rchild==NULL) ||  
    119.             (pre!=NULL && (cur->lchild==pre || cur->rchild==pre)))      
    120.         {                               /*如果当前结点没有孩子结点或者孩子节点都已被访问过*/  
    121.             std::cout<<cur->data<<" ";  
    122.             stk.pop();  
    123.             pre = cur;  
    124.         }  
    125.         else  
    126.         {  
    127.             if(cur->rchild!=NULL)  
    128.                 stk.push(cur->rchild);  
    129.             if(cur->lchild!=NULL)  
    130.                 stk.push(cur->lchild);  
    131.         }  
    132.     }  
    133. }  


    2)main文件

    [cpp] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. #include"BiTree.h"  
    2. using namespace std;  
    3. int main()  
    4. {  
    5.     BiTNode *T=new BiTNode;  
    6.     std::cout<<"请前序遍历输入各节点:";  
    7.     CreateBiTree(&T);  
    8.     cout<<" 该树的前序遍历输出为:"<<endl;  
    9.     PreOrderTraverse(T);  
    10.     cout<<endl;  
    11.     nPreOrderTraverse(T);  
    12.     cout<<" 该树的中序遍历输出为:"<<endl;  
    13.     InOrderTraverse(T);  
    14.     cout<<endl;  
    15.     nInOrderTraverse(T);  
    16.     cout<<" 该树的后序遍历输出为:"<<endl;  
    17.     PostOrderTraverse(T);  
    18.     cout<<endl;  
    19.     nPostOrderTraverse(T);  
    20.     cout<<endl;  
    21.     return 0;  
    22. }  

    5、测试结果

  • 相关阅读:
    孙陶然的五行文化,学习,真实用
    查看CPU使用率
    卸载windows补丁
    结束普通方法无法结束的进程
    三观
    如何知道一个EXE使用什么开发语言开发的
    文本文件处理,删除其中含有某些字符文本的行,一行命令搞定
    Delphi 字符串转日期,强大到窒息,VarToDateTime 解决了 困扰很久的小问题
    netstat -an查看到大量的TIME_WAIT状态的解决办法
    跨平台开发应用
  • 原文地址:https://www.cnblogs.com/zhizhan/p/4437963.html
Copyright © 2020-2023  润新知