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("内存分配出错.\n");  
  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("前序遍历:\n");  
  51.     PreOrderTraverse(T);  
  52.     printf("\n中序遍历:\n");  
  53.     InOrderTraverse(T);  
  54.     printf("\n后序遍历:\n");  
  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<<"\t";  
  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<<"\t";  
  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<<"\t";  
  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<<"\t";  
  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<<"\t";  
  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<<"\t";  
  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<<"\t";  
  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<<"\t";  
  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<<"\t";  
  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<<"\t";  
  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<<"\t";  
  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<<"\t";  
  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<<"\n该树的前序遍历输出为:"<<endl;  
  9.     PreOrderTraverse(T);  
  10.     cout<<endl;  
  11.     nPreOrderTraverse(T);  
  12.     cout<<"\n该树的中序遍历输出为:"<<endl;  
  13.     InOrderTraverse(T);  
  14.     cout<<endl;  
  15.     nInOrderTraverse(T);  
  16.     cout<<"\n该树的后序遍历输出为:"<<endl;  
  17.     PostOrderTraverse(T);  
  18.     cout<<endl;  
  19.     nPostOrderTraverse(T);  
  20.     cout<<endl;  
  21.     return 0;  
  22. }  

 

 

5、测试结果

 

posted @ 2015-04-18 20:07  止战  阅读(2248)  评论(0编辑  收藏  举报