二叉树先序、中序、后序遍历的非递归实现

来源:互联网 发布:淘宝定制的好不好 编辑:程序博客网 时间:2024/06/14 16:16

二叉树先序、中序、后序遍历的非递归实现

分类: 数据结构 ACM 746人阅读 评论(6) 收藏 举报
null算法structinput

 

在网上看了一些用非递归实现先序中序后序遍历二叉树的代码,都很混乱,while、if各种组合嵌套使用,逻辑十分不清晰,把我也搞懵了。想了大半天,写了大半天,突然开了窍,实际上二叉树的这三种遍历在逻辑上是十分清晰的,所以才可以用递归实现的那么简洁。既然逻辑如此清晰,那么用非递归实现也应该是清晰的。

自认为自己的代码比网上搜到的那些都清晰得多,好理解得多。

稍微解释一下:

先序遍历。将根节点入栈,考察当前节点(即栈顶节点),先访问当前节点,然后将其出栈(已经访问过,不再需要保留),然后先将其右孩子入栈,再将其左孩子入栈(这个顺序是为了让左孩子位于右孩子上面,以便左孩子的访问先于右孩子;当然如果某个孩子为空,就不用入栈了)。如果栈非空就重复上述过程直到栈空为止,结束算法。

中序遍历。将根节点入栈,考察当前节点(即栈顶节点),如果其左孩子未被访问过(有标记),则将其左孩子入栈,否则访问当前节点并将其出栈,再将右孩子入栈。如果栈非空就重复上述过程直到栈空为止,结束算法。

后序遍历。将根节点入栈,考察当前节点(即栈顶节点),如果其左孩子未被访问过,则将其左孩子入栈,否则如果其右孩子未被访问过,则将其右孩子入栈,如果都已经访问过,则访问其自身,并将其出栈。如果栈非空就重复上述过程直到栈空为止,结束算法。

其实,这只不过是保证了先序中序后序三种遍历的定义。对于先序,保证任意一个节点先于其左右孩子被访问,还要保证其左孩子先于右孩子被访问。对于中序,保证任意一个节点,其左孩子先于它被访问,右孩子晚于它被访问。对于后序,保证任意一个节点的左孩子右孩子都先于它被访问,其中左孩子先于右孩子被访问。如是而已。

代码里应该体现得比较清楚。这里不光给出了非递归版本,也给出了递归版本。

[cpp] view plaincopy
  1. #include <iostream>  
  2. #include <stack>  
  3.    
  4. using namespace std;  
  5.    
  6. struct TreeNode   
  7. {  
  8.     int data;  
  9.     TreeNode* left;  
  10.     TreeNode* right;  
  11.     int flag;  
  12. };  
  13.    
  14. typedef TreeNode *TreePtr;  
  15.    
  16. TreePtr CreateTree()  
  17. {  
  18.     TreePtr root = new TreeNode;  
  19.     cout<<"input the data :/n";  
  20.     int n;  
  21.     cin>>n;  
  22.     if (n == -1)  
  23.     {  
  24.         return NULL;  
  25.     }   
  26.     else  
  27.     {  
  28.         root->data = n;  
  29.         root->flag = 0;  
  30.         root->left = CreateTree();  
  31.         root->right = CreateTree();  
  32.     }  
  33.     return root;  
  34. }  
  35.    
  36. void PreOrderRecursion(TreePtr p)  
  37. {  
  38.     if (p == NULL)  
  39.     {  
  40.         return;  
  41.     }  
  42.     cout<<p->data<<" ";  
  43.     PreOrderRecursion(p->left);  
  44.     PreOrderRecursion(p->right);  
  45. }  
  46.    
  47. void InOrderRecursion(TreePtr p)  
  48. {  
  49.     if (p == NULL)  
  50.     {  
  51.         return;  
  52.     }  
  53.     InOrderRecursion(p->left);  
  54.     cout<<p->data<<" ";  
  55.     InOrderRecursion(p->right);  
  56. }  
  57.    
  58. void PostOrderRecursion(TreePtr p)  
  59. {  
  60.     if (p == NULL)  
  61.     {  
  62.         return;  
  63.     }  
  64.     PostOrderRecursion(p->left);  
  65.     PostOrderRecursion(p->right);  
  66.     cout<<p->data<<" ";  
  67. }  
  68.    
  69. void PreOrderNoRecursion(TreePtr p)  
  70. {  
  71.     cout<<"PreOrderNoRecursion/n";  
  72.    
  73.     stack<TreeNode> stk;  
  74.     TreeNode t = *p;  
  75.     stk.push(t);  
  76.    
  77.     while (!stk.empty())  
  78.     {  
  79.         t = stk.top();  
  80.         stk.pop();  
  81.         cout<<t.data<<" ";  
  82.    
  83.         if (t.right != NULL)  
  84.         {  
  85.             stk.push((*t.right));  
  86.         }  
  87.    
  88.         if (t.left != NULL)  
  89.         {  
  90.             stk.push((*t.left));  
  91.         }  
  92.     }  
  93. }  
  94.    
  95. void InOrderNoRecursion(TreePtr p)  
  96. {  
  97.     cout<<"InOrderNoRecursion/n";  
  98.    
  99.     stack<TreeNode> stk;  
  100.     TreeNode t = *p;  
  101.     stk.push(t);  
  102.    
  103.     while (!stk.empty())  
  104.     {  
  105.         if (stk.top().flag == 0)  
  106.         {  
  107.             stk.top().flag++;  
  108.             if (stk.top().left != NULL)  
  109.             {  
  110.                 stk.push(*(stk.top().left));  
  111.             }  
  112.         }  
  113.         else  
  114.         {  
  115.             t = stk.top();  
  116.             stk.pop();  
  117.             cout<<t.data<<" ";  
  118.             if (t.right != NULL)  
  119.             {  
  120.                 stk.push(*(t.right));  
  121.             }  
  122.         }  
  123.     }  
  124. }  
  125.    
  126. void PostOrderNoRecursion(TreePtr p)  
  127. {  
  128.     cout<<"PostOrderNoRecursion/n";  
  129.    
  130.     stack<TreeNode> stk;  
  131.     TreeNode t = *p;  
  132.     stk.push(t);  
  133.    
  134.     while (!stk.empty())  
  135.     {  
  136.         if (stk.top().flag == 0)  
  137.         {  
  138.             stk.top().flag++;  
  139.             if (stk.top().left != NULL)  
  140.             {  
  141.                 stk.push(*(stk.top().left));  
  142.             }  
  143.         }   
  144.         else if (stk.top().flag == 1)  
  145.         {  
  146.             stk.top().flag++;  
  147.             if (stk.top().right != NULL)  
  148.             {  
  149.                 stk.push(*(stk.top().right));  
  150.             }  
  151.         }   
  152.         else  
  153.         {  
  154.             cout<<stk.top().data<<" ";  
  155.             stk.pop();  
  156.         }  
  157.     }  
  158. }  
  159.    
  160. int main()  
  161. {  
  162.     TreePtr t = CreateTree();  
  163.    
  164.     cout<<"PreOrderRecursion/n";  
  165.     PreOrderRecursion(t);  
  166.     cout<<"/n";  
  167.    
  168.     cout<<"InOrderRecursion/n";  
  169.     InOrderRecursion(t);  
  170.     cout<<"/n";  
  171.    
  172.     cout<<"PostOrderRecursion/n";  
  173.     PostOrderRecursion(t);  
  174.     cout<<"/n";  
  175.    
  176.     PreOrderNoRecursion(t);  
  177.     cout<<"/n";  
  178.    
  179.     InOrderNoRecursion(t);  
  180.     cout<<"/n";  
  181.    
  182.     PostOrderNoRecursion(t);  
  183.     cout<<"/n";  
  184. }  

1 0