遍歷二叉樹

對二叉樹以前序遍歷、中序遍歷、後序遍歷三種方式遞歸及非遞歸的方式遍歷樹。


/**
 * 文件名:VisitTree.cpp
 * 功能:分別對二叉樹以前、中、後三種方式遞歸及非遞歸的方式遍歷樹。
 * 作者:Neicole
 * 日期:2013.06.08
 * 聯繫:http://blog.csdn.net/neicole
 **/
#pragma once
#include <iostream>
#include <stack>
using std::cout;
using std::stack;
/**********************************************************************/
/****************************   聲明   ********************************/
/**********************************************************************/
// 二叉樹結點類
class TreeNode
{
public:
    int elem;
    TreeNode * lChild;
    TreeNode * rChild;
public:
    TreeNode():elem(0), lChild(NULL), rChild(NULL){}
    int display(){ cout << elem; return 0;}
}* head(NULL);
// 前序遍歷
int preOrderRecursion(TreeNode* node);  // 遞歸
int preOrder(TreeNode* node);           // 非遞歸
// 中序遍歷
int inOrderRecursion(TreeNode* node);   // 遞歸
int inOrder(TreeNode* node);            // 非遞歸
// 後序遍歷
int postOrderRecursion(TreeNode * node);// 遞歸
int postOrder(TreeNode* node);          // 非遞歸
/**********************************************************************/
/****************************   實現  *********************************/
/**********************************************************************/
// 前序遍歷-遞歸
int preOrderRecursion(TreeNode* node)
{
    if(NULL == node){
        return 0;
    }
    node -> display();       // 顯示本節點
    preOrderRecursion(node -> lChild);   // 左孩子
    preOrderRecursion(node -> rChild);   // 右孩子
    return 0;
}
// 前序遍歷-非遞歸(遞歸思想)
int preOrder(TreeNode* node)
{
    stack<TreeNode*> s;
    s.push(node);
      
    while(!s.empty()){
        node = s.top();
        s.pop();
        node -> display();
        if(NULL != node -> lChild){
            s.push(node -> lChild);
        }
        if(NULL != node -> rChild){
            s.push(node -> rChild);
        }
    }
    return 0;
}
// 前序遍歷-非遞歸(深度遍歷思想)[歸納法]
int preOrder2(TreeNode* node)
{
    stack<TreeNode*> s;
      
    while(NULL != node || !s.empty()){
       while(NULL != node){
           node -> display();
           s.push(node);
           node = node -> lChild;
       }
       if(!s.empty()){
           node = s.top();
           s.pop();
           node = node -> rChild;
       }
    }
    return 0;
}
// 中序遍歷-遞歸
int inOrderRecursion(TreeNode* node)
{
    if(NULL == node){
        return 0;
    }
    inOrderRecursion(node -> lChild);    // 左孩子
    node -> display();                   // 顯示本結點
    inOrderRecursion(node -> rChild);    // 右孩子
    return 0;
}
// 中序遍歷-非遞歸(樹的某結點的五種形式的思想)
int inOrder(TreeNode* node)
{
    stack<TreeNode*> s;
      
    // 節點有五種狀態:
    // 1.雙節點,2.只有左孩子 3.只有右孩子 4.葉子  5.非結點
    // 動態的,再劃分兩種狀態:(程序使用bool作爲開關)
    // 1.進入態  2.回朔態
    // 一共是5*2=10種狀態
    bool entrance = true;
    while(NULL != node){
        if(entrance){   // 進入態
            // 1.雙節點  2. 只有左孩子,兩種狀態使用同一種方法
            if(NULL != node -> lChild){
                s.push(node);
                node = node -> lChild;
                continue;
            }
            // 3. 只有右孩子
            else if(NULL != node -> rChild){
                node -> display();
                node = node -> rChild;
                continue;
            }
        }
        else{           // 回朔態
            // 1. 雙節點
            if(NULL != node -> lChild && NULL != node -> rChild){
                node -> display();
                node = node -> rChild;
                entrance = true;            // 轉換爲進入態
                continue;
            }
            // 2. 只有左孩子
            else if(NULL != node -> lChild){
                node -> display();
                node = s.top();
                s.pop();
                continue;
            }
        }
        // 4. 葉子結點
        if(NULL == node -> lChild && NULL == node -> rChild){
            node -> display();
        // 5.(如果往下遍歷的話)非結點的回溯
            if(!s.empty()){
                node = s.top();
                s.pop();
                entrance = false;
            }
            else{
                node = NULL;    // 方便下次跳出循環
            }
        }  
    }
    return 0;
}
// 中序遍歷-非遞歸(深度遍歷思想)[歸納法]
int inOrder2(TreeNode* node)
{
    stack<TreeNode*> s;
    s.push(node);
      
    while(!s.empty()){
        while(NULL != node){
            s.push(node -> lChild);
            node = node -> lChild;
        }
        if(!s.empty()){
            node = s.top();
            s.pop();
            node -> display();
            node = node -> rChild;
        }
    }
    return 0;
}
// 後序遍歷-遞歸
int postOrderRecursion(TreeNode * node)
{
    if(NULL == node){
        return 0;
    }
    postOrderRecursion(node -> lChild);  // 左子樹訪問
    postOrderRecursion(node -> rChild);  // 右子樹訪問
    node -> display();                   // 顯示本節點
    return 0;
}
// 後序遍歷-非遞歸(樹的某結點的五種形式的思想)
int postOrder(TreeNode* node)
{
    stack<TreeNode*> s;
    bool entrance = true;
    // 節點有五種狀態:
    // 1.雙節點,2.只有左孩子 3.只有右孩子 4.葉子  5.非結點
    // 動態的,再劃分兩種狀態:(程序使用bool作爲開關)
    // 1.進入態  2.回朔態
    while(NULL != node){
        if(entrance){
            // 1.雙孩子
            if(NULL != node -> lChild && NULL != node -> rChild){
                s.push(node);           // 存本節點
                s.push(node -> rChild);  // 存雙重右結點(也是作爲雙結點的標誌)
                s.push(node -> rChild);
                node = node -> lChild;   // 進入左結點
                continue;
            }
            // 2.左孩子
            else if(NULL != node -> lChild){
                s.push(node);           // 存本結點
                node = node -> lChild;
                continue;
            }
            // 3.右孩子
            else if(NULL != node -> rChild){
                s.push(node);           // 存本結點
                node = node -> rChild;
                continue;
            }
            // 4.葉子
            else if(NULL == node -> lChild && NULL == node -> rChild){
                node -> display();       // 顯示結點
            }
        }
        else{
            // 回溯態,1.2.3.4均顯示結點
            node -> display();
        }
        // 5. 無結點,開始回溯
        if(s.empty()){
            node = s.top();
            s.pop();
            if(!s.empty()){ // 判斷是否右結點
                if(s.top() == node){
                    entrance = true;    // 轉換爲進入態
                    continue;
                }
            }
            entrance = false;
        }
    }
    return 0;
}
// 主函數
int main()
{
    system("pause");
    return 0;
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章