中序树转换非递归

没头没脑琢磨了一整晚,什么P也没整出来,人不能不服老啊。。。

其实以前看过,只是看懂而已,没有深刻理解;出来混总是要还得!

以前从没有想过:初始条件是什么?什么时候进栈?什么时候出栈?终止条件是什么?

一看题目就想如何模拟递归的方式实现。结果就载着各种细节中,而且越陷越深;想当年看递归也是这么陷入进去。。。

这次卡就卡在了,什么时候出栈?是什么条件导致出栈?

出栈原因很简单,遇到空指针则需要出栈了。结果进栈的时候,我还判断是否为空,空就不进栈,然后,然后就没有然后了。。。。

这个是卡死的关键点,起码是我之前没有去想的。

试想N个节点不是有N+1个空指针么?如果遇到一个空指针,就退栈一个节点不是OK了么~是不是豁然开朗,反正我当时茅”厕“顿开了。。。

还有最后多一个空指针,怎么办?判断一下撒~

  1 #include <iostream>
  2 #include <stack>
  3 
  4 using namespace std;
  5 
  6 struct SBinaryTreeNode // a node of the binary tree
  7 {
  8     int               m_nValue; // value of node
  9     SBinaryTreeNode  *m_pLeft;  // left child of node
 10     SBinaryTreeNode  *m_pRight; // right child of node
 11 };
 12 
 13 void PrintTree(const SBinaryTreeNode *root);
 14 void CreateTree(SBinaryTreeNode **root);
 15 
 16 void minOrderLoop1(SBinaryTreeNode * root)
 17 {
 18     stack<SBinaryTreeNode*> s;
 19     SBinaryTreeNode *p;
 20 
 21     p = root;
 22     s.push(root);
 23     
 24     while(p || !s.empty())
 25     {
 26         if (p)
 27         {
 28             s.push(p->m_pLeft);
 29             p = p->m_pLeft;
 30         }
 31         else  //指向空指针
 32         {
 33             s.pop();
 34             if (s.empty())  //最后的空指针判断
 35             {
 36                 break;
 37             }
 38             p = s.top();
 39             s.pop();
 40             printf("%d ", p->m_nValue);
 41 
 42             s.push(p->m_pRight);
 43             p = p->m_pRight;
 44         }
 45     }
 46 }
 47 
 48 void minOrderLoop2(SBinaryTreeNode * root)
 49 {
 50     stack<SBinaryTreeNode*> s;
 51     SBinaryTreeNode *p;
 52 
 53     s.push(root);
 54 
 55     while(!s.empty())
 56     {
 57         p = s.top();
 58         while(p)
 59         {
 60             s.push(p->m_pLeft);
 61             p = p->m_pLeft;
 62         }
 63 
 64         s.pop();
 65 
 66         if (!s.empty())  
 67         {
 68             p = s.top();
 69             s.pop();
 70             printf("%d ", p->m_nValue);
 71             s.push(p->m_pRight);
 72     
 73         }
 74     }
 75 }
 76 
 77 FILE *fp;
 78 SBinaryTreeNode *prev=NULL;
 79 
 80 int main()
 81 {
 82     SBinaryTreeNode *root=NULL;
 83     SBinaryTreeNode *cur=NULL;
 84     
 85     
 86     fp = fopen("test.txt", "r");
 87     
 88     if (!fp)
 89     {
 90         printf("can not open the file.\n");
 91         return -1;
 92     }
 93     
 94     CreateTree(&root);
 95     PrintTree(root);
 96     
 97     cout<<endl;
 98 
 99     minOrderLoop1(root);
100     cout<<endl;
101     minOrderLoop2(root);
102     cout<<endl;
103 
104     
105     
106     return 0;
107 }
108 
109 void CreateTree(SBinaryTreeNode **root)
110 {
111     int val;
112     
113     //scanf("%d",&val);
114     fscanf(fp, "%d", &val);
115     if (val==0)
116     {
117         *root = NULL;
118         return;
119     }
120     
121     *root = (SBinaryTreeNode*)malloc(sizeof(SBinaryTreeNode));
122     (*root)->m_nValue = val;
123     
124     CreateTree(&(*root)->m_pLeft);
125     CreateTree(&(*root)->m_pRight);
126 }
127 
128 void PrintTree(const SBinaryTreeNode *root)
129 {
130     if (!root)
131     {
132         return;
133     }
134     PrintTree(root->m_pLeft);
135     printf("%d ", root->m_nValue);
136     
137     PrintTree(root->m_pRight);
138 }

 先序树就比较简单了(基本一致就是输出的位置不一样):

 1 void preOrderLoop1(SBinaryTreeNode * root)
 2 {
 3     stack<SBinaryTreeNode*> s;
 4     SBinaryTreeNode *p;
 5     
 6     p = root;
 7     s.push(root);
 8     
 9     while(p || !s.empty())
10     {
11         if (p)
12         {
13             printf("%d ", p->m_nValue);
14             s.push(p->m_pLeft);
15             p = p->m_pLeft;
16         }
17         else  //指向空指针
18         {
19             s.pop();
20             if (s.empty())
21             {
22                 break;
23             }
24             p = s.top();
25             s.pop();            
26             
27             s.push(p->m_pRight);
28             p = p->m_pRight;
29         }
30     }
31 }
32 
33 void preOrderLoop2(SBinaryTreeNode * root)
34 {
35     stack<SBinaryTreeNode*> s;
36     SBinaryTreeNode *p;
37     
38     s.push(root);
39     
40     while(!s.empty())
41     {
42         p = s.top();
43         while(p)
44         {
45             printf("%d ", p->m_nValue);
46             s.push(p->m_pLeft);
47             p = p->m_pLeft;
48         }
49         
50         s.pop();
51         
52         if (!s.empty())
53         {
54             p = s.top();
55             s.pop();            
56             s.push(p->m_pRight);
57             
58         }
59     }
60 }

至于后序树就比较麻烦了:

 先对树的节点结构修改为

1 struct SBinaryTreeNode // a node of the binary tree
2 {
3     int               m_nValue; // value of node
4     SBinaryTreeNode  *m_pLeft;  // left child of node
5     SBinaryTreeNode  *m_pRight; // right child of node
6     bool            visited; //添加访问标示位
7 };

后序树非递归算法:

 1 void postLoop(SBinaryTreeNode* root)
 2 {
 3     stack<SBinaryTreeNode*> s;
 4     SBinaryTreeNode * p;
 5 
 6     if (!root)
 7     {
 8         return;
 9     }
10     s.push(root);
11 
12     while(!s.empty())
13     {
14         p = s.top();
15 
16         if (p->m_pLeft && !p->m_pLeft->visited)
17         {
18             s.push(p->m_pLeft);
19         }
20         else if (p->m_pRight && !p->m_pRight->visited)
21         {
22             s.push(p->m_pRight);
23         }
24         else if (p->m_pRight==NULL || p->m_pRight->visited)
25         {
26             printf("%d ", p->m_nValue);
27             p->visited=true;
28             s.pop();
29         }
30     }
31 }

 最后的后序树是不能简单的像前两种的方式进行。注意到,后序树的递归是不一样的:

 1 void PostPrintTree(const SBinaryTreeNode *root)
 2 {
 3     if (!root)
 4     {
 5         return;
 6     }
 7     
 8     PostPrintTree(root->m_pLeft);    
 9     PostPrintTree(root->m_pRight);
10     printf("%d ", root->m_nValue);
11 }

其实就是什么尾递归啊什么的。。。

它们转换为非递归的方式有点不一样,现在没有深究。。。。

参考:递归算法转换为非递归算法

posted @ 2013-04-02 09:32  legendmaner  阅读(195)  评论(0编辑  收藏  举报