二叉树前序、中序、后序遍历的非递归写法

数据结构定义

struct Node{
    char c;
    pNode lchild, rchild;
    Node(char c, pNode lchild = nullptr, pNode rchild = nullptr) :
        c(c), lchild(lchild), rchild(rchild) {}
};

二叉树形态:

       A
     /   \
    B     C
   / \   / \
  D   E F   G
       / \
      H   I

前序遍历:

先根遍历:先判断节点的指针是否为空,不为空就先访问该结点,然后直接进栈,接着遍历左子树;为空则要从栈中弹出一个节点来,这个时候弹出的结点就是其父亲,然后访问其父亲的右子树,直到当前节点为空且栈为空时,算法结束.

中序遍历:

和前序遍历一样,但在访问节点的顺序不一样,访问节点的时机是从栈中弹出元素时访问,如果从栈中弹出元素,就意味着当前节点父亲的左子树已经遍历完成,这时候访问父亲,就是中序遍历.

后序遍历:

后续遍历,首先访问左子树,把父亲节点保存于栈中,问题是当元素从栈中弹出的时候,我们无法判断这个时候是该访问其右子树还是访问父亲节点,于是我们就需要一个标记,当访问左子树时我们把父亲节点的标记设为1,表示下一步如果弹出该节点,就访问其右子树;弹出一个节点时,我们要判断该节点的标记,如果是1,则访问其右子树,并把该节点的标记设置成2,表示下一步就访问该节点,然后把该节点继续入栈,如果是2,那么表示访问该节点,访问并且丢弃该节点.

为了不继续添加新的数据结构,我是用了STL中的pair来封装节点与标记.

测试代码:

#include <bits/stdc++.h>

using namespace std;

typedef struct Node *pNode;

struct Node{
    char val;
    pNode lchild, rchild;
    Node(char c, pNode lchild = nullptr, pNode rchild = nullptr) :
        c(c), lchild(lchild), rchild(rchild) {}
};

//按照前序顺序建立二叉树
void createBiTree(pNode &T) //&的意思是传进来节点指针的引用,括号内等价于 Node* &T,目的是让传递进来的指针发生改变
{                        
    char c;
    cin >> c;
    if('#' == c)             //当遇到#时,令树的根节点为NULL,从而结束该分支的递归
        T = NULL;
    else
    {
        T = new Node;
        T->val = c;
        createBiTree(T->lchild);
        createBiTree(T->rchild);
    }
}

pNode build()
{
    /*
             A
           /  \
         B     C
        / \   / \
       D   E F   G
            / \
           H   I
    */
    pNode root = new Node('A');
    root->lchild = new Node('B');
    root->rchild = new Node('C');
    root->lchild->lchild = new Node('D');
    root->lchild->rchild = new Node('E');
    root->rchild->lchild = new Node('F');
    root->rchild->rchild = new Node('G');
    root->rchild->lchild->lchild = new Node('H');
    root->rchild->lchild->rchild = new Node('I');
    return root;
}

void visit(pNode x)
{
    cout << x->val << " ";
}

void preVisitStack(pNode root)
{
    stack<pNode> st;
    pNode p = root;
    while (p || !st.empty()) {
        if (p) {
            visit(p);
            st.push(p);
            p = p->lchild;
        } else {
            p = st.top();
            st.pop();
            p = p->rchild;
        }
    }
    cout << endl;
}

void midVisitStack(pNode root)
{
    stack<pNode> st;
    pNode p = root;
    while (p || !st.empty()) {
        if (p) {
            st.push(p);
            p = p->lchild;
        } else {
            p = st.top();
            visit(p);
            st.pop();
            p = p->rchild;
        }
    }
    cout << endl;
}

void backVisitStack(pNode root)
{
    stack<pair<pNode, int> > st;
    pNode p = root;
    while (p || !st.empty()) {
        if (p) {
            st.push(make_pair(p, 1));
            p = p->lchild;
        } else {
            auto now = st.top();
            st.pop();
            if (now.second == 1) {
                st.push(make_pair(now.first, 2));
                p = now.first->rchild;
            } else
                visit(now.first);
        }
    }
    cout << endl;
}

int main()
{
    createBiTree(*root);
    preVisitStack(root);
    midVisitStack(root);
    backVisitStack(root);
}

测试结果:
前序遍历:  A B D E C F H I G 
中序遍历:  D B E A H F I C G 
后序遍历:  D E B H I F G C A 

猜你喜欢

转载自blog.csdn.net/qq_40803710/article/details/81228355