二叉樹的先序、中序、後序遞歸與非遞歸實現遍歷

//定義二叉樹結點
struct BiTreeNode
{
    int data;
    BiTreeNode* left;
    BiTreeNode* right;      
};

1、遞歸實現post

//先序
void preOrder(BiTreeNode *root){
    cout<<root->data;
    preOrder(root->left);
    preOder(root->right);
}

//中序
void inOrder(BiTreeNode *root){
    preOrder(root->left);
    cout<<root->data;
    preOder(root->right);
}

//後序
void postOrder(BiTreeNode *root){
    preOrder(root->left);
    preOder(root->right);
    cout<<root->data;
}

以上的cout<<root->data;是對結點的一種操做,這裏能夠對結點作任意想作的操做。spa

2、非遞歸實現指針

//先序
void preOrderS(Node *root)   
{
    stack<Node*> s;
    Node *p=root;
    while(p!=NULL||!s.empty())
    {
        //沿着左支走到底
        //用棧記錄走過的路徑
        while(p!=NULL)
        {
            cout<<p->data<<" ";
            s.push(p);
            p=p->left;
        }
        
        //當左支走到盡頭時,若棧裏邊還有結點
        //則退棧,後退到跟結點,而且向右支前進
        //此時p!=NULL,會進入以上while循環
        if(!s.empty())
        {
            p=s.top();
            s.pop();
            p=p->right;
        }
    }
}
//注:在 if(!s.empty())中,獲取根結點只是爲了獲得往右支的中轉,
//當得到右支指針後,將根結點從棧中彈出,以便返回的時候直接
//回到爺爺結點


//中序
void inOrderS(Node *root){
    stack<Node*> s;
    Node *p=root;
    while(p!=NULL||!s.empty()){
        while(p!=NULL)){
            s.push(p);
            p=p->left;
        }
        if(!s.empty()){
            p=s.top();
            s.pop();
            cout<<p->data;
            p=p->right;
        }
    }
}
//中序遍歷和先序遍歷的代碼幾乎一致,除了訪問點的位置不同
//中序遍歷是在退棧的時候訪問根結點

//後序 void PostOrderS(Node *root) { Node *p = root, *r = NULL; stack<Node*> s; while (p!=NULL || !s.empty()) { if (p!=NULL) {//走到最左邊 s.push(p); p = p->left; } else { p = s.top(); if (p->right!=NULL && p->right != r)//右子樹存在,未被訪問 p = p->right; else { s.pop(); visit(p->val); r = p;//記錄最近訪問過的節點 p = NULL;//節點訪問完後,重置p指針 } }//else }//while } //由於後序非遞歸遍歷二叉樹的順序是先訪問左子樹,再訪問右子樹,最後訪問根節點。當用
//堆棧來存儲節點,必須分清返回根節點時,是從左子樹返回的,還從右子樹返回的。因此,
//使用輔助指針r,其指向最近訪問過的節點。也能夠在節點中增長一個標誌域,記錄是否已被
//訪問
相關文章
相關標籤/搜索