二叉樹遍歷
阿新 • • 發佈:2017-10-11
while nbsp .net right 三種 pos tail stack實現 order
二叉樹遍歷最簡單的就是遞歸了。因為遞歸實質上是棧存了一些中間值,所以我們可以使用stack實現叠代版的遍歷。
- 中序遍歷
步驟:
首先將root節點作為當前節點。
1.如果當前節點不為空,壓入當前節點。將左節點作為當前節點。
2.否則彈出棧頂節點作為當前節點,輸出當前節點。
3.如果右節點不為空,右節點作為當前節點。
4.否則將當前節點置為空。
重復1、2、3、4直到棧為空。
void InorderTraversal(TreeNode *root){ if(!root)return; TreeNode *node=root; stack<TreeNode*> mystk; while(node||mystk.size()){ while(node){ mystk.push(node); node=node->left; } node=mystk.top(); mystk.pop(); cout<<node->val<<‘\t‘; if(node->right){ node=node->right; }else{ node=NULL; } } }
- 前序遍歷
前序遍歷和中序遍歷差不多,只是輸出節點值的時機不同。
步驟:
以root節點作為當前節點
1.如果當前節點不為空,將當前節點壓入棧,同時輸出當前節點。並將左節點作為當前節點。
2.否則彈出棧頂作為當前節點。
3.如果右節點不為空,將右節點作為當前節點。
4.否則將當前節點置為空。
重復1、2、3、4直到棧為空。
void PreorderTraversal(TreeNode *root){ if(!root)return; TreeNode*node=root; stack<TreeNode*> mystk; while(node||mystk.size()){ while(node){ mystk.push(node); cout<<node->val<<‘\t‘; node=node->left; } node=mystk.top(); mystk.pop(); if(node->right){ node=node->right; }else{ node=NULL; } } }
- 後序遍歷
後序遍歷有點特殊,需要一個輔助節點記錄是否遍歷過了。
步驟:
將root節點作為當前節點
1.如果當前節點不為空,將當前節點壓入棧中。將左節點作為當前節點。
2.否則,將棧頂節點(不彈出)作為當前節點。
3.如果右節點不為空且右節點不等於pre節點,將右節點作為當前節點。
4.否則,輸出當前節點,pop棧頂,並將當前節點作為pre節點。設置當前節點為空。
重復1、2、3、4直到棧為空。
void PostorderTraversal(TreeNode *root){ if(!root)return; TreeNode *node=root; TreeNode *pre=NULL; stack<TreeNode*> mystk; while(node||mystk.size()){ while(node){ mystk.push(node); node=node->left; } node=mystk.top(); if(node->right&&node->right!=pre){ node=node->right; }else{ cout<<node->val<<‘\t‘; mystk.pop(); pre=node; node=NULL; } } }
上述三種遍歷對於每個節點都是入棧一次出棧一次,所以時間復雜度和空間復雜度都是o(n)。
而Morris遍歷則可以o(1)完成各種遍歷。下面解釋morris遍歷。
- Morris遍歷
morris遍歷的精髓是提出了前驅節點的概念:即輸出前驅節點後,下一個輸出的就是當前節點。
參考http://blog.csdn.net/zhaoyunfullmetal/article/details/48087663
二叉樹遍歷