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

简介:

前序和中序遍历的非递归写法都比较好实现,后序遍历稍微复杂一些.

数据结构定义:

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
2
3
4
5
6
7
前序遍历:

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

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;

}

后序遍历:

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

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

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;

}

完整测试代码:

include

using namespace std;

typedef struct Node *pNode;

struct Node{

char c;
pNode lchild, rchild;
Node(char c, pNode lchild = nullptr, pNode rchild = nullptr) :
    c(c), lchild(lchild), rchild(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->c << " ";

}

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()
{

pNode root = build();
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

相关文章
|
存储 算法 C++
【二叉树】利用前序和中序遍历结果生成二叉树并输出其后序和层序遍历结果
【二叉树】利用前序和中序遍历结果生成二叉树并输出其后序和层序遍历结果
160 0
非递归方式实现二叉树的前、中、后序遍历
非递归方式实现二叉树的前、中、后序遍历
|
算法 C语言
【递归调用在二叉树中的应用】前序遍历、中序遍历、后序遍历、求二叉树叶子结点及复制二叉树的C语言实现
【递归调用在二叉树中的应用】前序遍历、中序遍历、后序遍历、求二叉树叶子结点及复制二叉树的C语言实现
159 0
【递归调用在二叉树中的应用】前序遍历、中序遍历、后序遍历、求二叉树叶子结点及复制二叉树的C语言实现
|
iOS开发
二叉树非递归前中后遍历
因为个人身体原因,本周都在医院住院治疗身体,身边没有电脑,只能分享一些这周看过的比较好的书籍内容。iPad上传csdn图片顺序会有误,看书的页码就好。
二叉树非递归前中后遍历
|
开发工具
15分钟精通二叉树,二叉树的先序,中序,后序,层次遍历顺序
🍀🍀🍀理解,掌握二叉树先序,中序,后序,层次四种遍历顺序
186 0
15分钟精通二叉树,二叉树的先序,中序,后序,层次遍历顺序
|
数据采集 算法
数据结构与算法—二叉树的层序、前序中序后序(递归、非递归)遍历
层序遍历。听名字也知道是按层遍历。我们知道一个节点有左右节点。而每一层一层的遍历都和左右节点有着很大的关系。也就是我们选用的数据结构不能一股脑的往一个方向钻,而左右应该均衡考虑。这样我们就选用队列来实现。
209 0
数据结构与算法—二叉树的层序、前序中序后序(递归、非递归)遍历
|
Java
二叉树面试题:前中序求后序、中后序求前序
在面试时,避免不了的会遇到一些数据结构的面试题,今天我们就来了解一下二叉树的经典面试题:
159 0
二叉树非递归后序遍历
二叉树非递归后序遍历 二叉树非递归后序遍历
97 0