1. 程式人生 > >二叉樹遍歷

二叉樹遍歷

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

二叉樹遍歷