您现在的位置是:首页 > 文章详情

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

日期:2020-05-26点击:419

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

数据结构定义:

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
前序遍历:

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

前提:若后期有需求购买阿里云任何产品的朋友,可以提前领取优惠劵。后期可为大家减少成本:点击领取2000元阿里云优惠劵

void preVisitStack(pNode root)
{

stack 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 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 > 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 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 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 > 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

原文链接:https://yq.aliyun.com/articles/762631
关注公众号

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。

持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。

转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。

文章评论

共有0条评论来说两句吧...

文章二维码

扫描即可查看该文章

点击排行

推荐阅读

最新文章