二叉树的非递归遍历

1.前序遍历

对于任一结点P:

 1)访问结点P,并将结点P入栈;

 2)判断结点P的左孩子是否为空,若为空,则取栈顶结点并进行出栈操作,并将栈顶结点的右孩子置为当前的结点P,循环至1);
 若不为空,则将P的左孩子置为当前的结点P;

 3)直到P为NULL并且栈为空,则遍历结束。
//非递归先序遍历
void preOrder2(node *root){
    stack<node*> stk;
    node* p = root;

    while (p != NULL || !stk.empty()){
        while (p != NULL){
            cout << p->val << " ";
            stk.push(p);
            p = p->left;
        }

        if (!stk.empty()){
            p = stk.top();
            stk.pop();
            p = p->right;
        }
    }
}

3.中序遍历

对于任一结点P,

1)若其左孩子不为空,则将P入栈并将P的左孩子置为当前的P,然后对当前结点P再进行相同的处理;

2)若其左孩子为空,则取栈顶元素并进行出栈操作,访问该栈顶结点,然后将当前的P置为栈顶结点的右孩子;

3)直到P为NULL并且栈为空则遍历结束

//非递归中序遍历
void inOrder2(node* root){
    stack<node*> stk;
    node* p = root;
    while (p != NULL || !stk.empty()){
        while (p != NULL){
            stk.push(p);
            p=p->left;
        }

        if (!stk.empty()){
            p = stk.top();
            stk.pop();
            cout << p->val<<" ";
            p = p->right;
        }

    }
}

3。后序遍历

后序遍历的非递归实现是三种遍历方式中最难的一种。因为在后序遍历中,要保证左孩子和右孩子都已被访问并且左孩子在右孩子前访问才能访问根结点。
对于任一结点P,将其入栈,然后沿其左子树一直往下搜索,直到搜索到没有左孩子的结点,此时该结点出现在栈顶,但是此时不能将其出栈并访问,因此其右孩子还为被访问。
所以接下来按照相同的规则对其右子树进行相同的处理,当访问完其右孩子时,该结点又出现在栈顶,此时可以将其出栈并访问。这样就保证了正确的访问顺序。
可以看出,在这个过程中,每个结点都两次出现在栈顶,只有在第二次出现在栈顶时,才能访问它。因此需要多设置一个变量标识该结点是否是第一次出现在栈顶。

void postOrder2(node* root){
    stack<tmpNode*> stk;
    node* p = root;

    while (p != NULL || !stk.empty()){
        while (p != NULL){
            tmpNode *tpn = new tmpNode(p);
            stk.push(tpn);
            p = p->left;
        }

        if (!stk.empty()){

            tmpNode* top = stk.top();
            stk.pop();

            if (top->isFirst){
                top->isFirst = false;

                //重新压到栈中
                stk.push(top);

                p = top->u->right;
            }
            else{
                cout << top->u->val << " " ;
                p=NULL;
            }

        }

    }
}

.

完整代码

#include<iostream>
#include<string>
#include<sstream>
#include<stack>
using namespace std;


struct node{
    int val;
    node* left;
    node* right;
    node(int val) :val(val), left(NULL), right(NULL){}
};

struct tmpNode{
    node* u;
    bool isFirst;

    tmpNode(node* u) :u(u), isFirst(true){}
};

node* builtTreeHelper(istringstream& is){
    string str;
    is >> str;
    if (str == "#"){
        return NULL;
    }

    node *u = new node(atoi(str.c_str()));

    u->left = builtTreeHelper(is);
    u->right = builtTreeHelper(is);

    return u;
}

node* builtTree(string str){
    istringstream is(str);

    node* root = builtTreeHelper(is);

    return root;
}

void preOrder(node *root){
    if (root){
        cout << root->val << " ";
    }

    if (root->left)
        preOrder(root->left);

    if (root->right)
        preOrder(root->right);
}

//非递归先序遍历
void preOrder2(node *root){
    stack<node*> stk;
    node* p = root;

    while (p != NULL || !stk.empty()){
        while (p != NULL){
            cout << p->val << " ";
            stk.push(p);
            p = p->left;
        }

        if (!stk.empty()){
            p = stk.top();
            stk.pop();
            p = p->right;
        }
    }
}

//非递归中序遍历
void inOrder2(node* root){
    stack<node*> stk;
    node* p = root;
    while (p != NULL || !stk.empty()){
        while (p != NULL){
            stk.push(p);
            p=p->left;
        }

        if (!stk.empty()){
            p = stk.top();
            stk.pop();
            cout << p->val<<" ";
            p = p->right;
        }

    }
}


void postOrder2(node* root){
    stack<tmpNode*> stk;
    node* p = root;

    while (p != NULL || !stk.empty()){
        while (p != NULL){
            tmpNode *tpn = new tmpNode(p);
            stk.push(tpn);
            p = p->left;
        }

        if (!stk.empty()){

            tmpNode* top = stk.top();
            stk.pop();

            if (top->isFirst){
                top->isFirst = false;

                //重新压到栈中
                stk.push(top);

                p = top->u->right;
            }
            else{
                cout << top->u->val << " " ;
            }

        }

    }
}


int main(){

    string str = "5 7 # 6 # # 3 # #";

    node* root = builtTree(str);

    cout << "先序遍历" << endl;
    preOrder2(root);

    cout << endl << "中序遍历" << endl;
    inOrder2(root);

    cout << endl<< "后序遍历" << endl;
    postOrder2(root);
    cout << endl;

    return 0;
}

参考
http://www.cnblogs.com/dolphin0520/archive/2011/08/25/2153720.html

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值