中序树转换非递归
没头没脑琢磨了一整晚,什么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 }
其实就是什么尾递归啊什么的。。。
它们转换为非递归的方式有点不一样,现在没有深究。。。。
参考:递归算法转换为非递归算法
毕