接着上面一篇博客,我们开始叙述有关二叉树的非递归遍历的实现。
这里我们附上上一篇blog的链接:https://blog.csdn.net/weixin_36997518/article/details/81370049,废话少说,直接上代码。
首先是二叉树的中序遍历,这是二叉树尤为重要的一种遍历方式,虽然它在三种非递归方式中是最简单的,但是很多算法都是基于这种方法进行再创作。
//中序遍历非递归方法
void tree::non_InOrder(node *t) {
if (t == NULL) {
return;
}
node *p = t;
stack<node*> s;//借助栈s来实现中序遍历
while (p || !s.empty()) {
if(p) {
s.push(p);
p = p->lchild;
}
else{
p = s.top();
cout << p->data << endl;
s.pop();
p = p->rchild;
}
}
}
前序遍历非递归方式:它和中序遍历可以说是完全相同,只是输出节点的位置略有不同而已。
//前序遍历非递归算法
void tree::non_PreOrder(node *t) {
if (t == NULL) {
return;
}
node *p = t;
stack<node*> s;//和中序遍历一样的过程,只是顺序改变了
while (p || !s.empty()) {
if(p) {
cout << p->data << endl;
s.push(p);
p = p->lchild;
}
else {
p = s.top();
s.pop();
p = p->rchild;
}
}
}
后序遍历:这是三种遍历方法中最为复杂的一种,因为它的根节点是最后访问的,在我们出栈遇到该节点时,我们并不知道此时它的右子树是否被访问过,所以我们需要额外借助一个节点变量用来判断右子树的访问真值。
//后序遍历非递归方法,这个和中序还有前序有一些区别
void tree::non_PostOrder(node *t) {
if (t == NULL) {
return;
}
node *p=t, *pre=NULL;
stack<node*> s;
while (p || !s.empty()) {
if (p) {
s.push(p);
p = p->lchild;
}
else {
p = s.top();
if (p->rchild&&p->rchild != pre) {//此时右子树还未遍历过,需要进行遍历
p = p->rchild;
s.push(p);
p = p->lchild;
}
else {//当右子树已经遍历过时,此时应该进行节点的输出
s.pop();
cout << p->data<<endl;
pre= p;
p = NULL;
}
}
}
}
以上就是三种遍历算法的非递归方式。这里给出完整的代码:
// 二叉树的构建.cpp: 定义控制台应用程序的入口点。
//作者:Daviu Liu
#include"stdafx.h"
#include<iostream>
#include<fstream>
#include<string.h>
#include<stack>
using namespace std;
typedef struct node {
int data;
struct node *lchild;
struct node *rchild;
//struct node(int x) :data(x), lchild(NULL), rchild(NULL) {};这种方法能够快速的构建节点
}node,*BiTree;
//二叉树的各种方法
class tree
{
public:
node *make_node(int number, string location);
node *root;
void non_PreOrder(node *t);
void non_InOrder(node *t);
void non_PostOrder(node *t);
//这里存放求树的深度等方法,先不写
};
//先序遍历的方法构建二叉树,这里我使用了递归,非递归的话也可以
//非递归方法将在之后给出
node* tree::make_node(int number, string location) {
int data;
node *p = new node;
cout << "请输入节点数据 " << endl;
cin >> data;
if (data == 0)//这里是用data=0代表空节点,要求每个叶子结点都要写出来,不然连树都不是
{
return NULL;
}
p->data = data;
p->lchild = make_node(number + 1, "left");
p->rchild = make_node(number + 1, "right");
return p;
}
//中序遍历非递归方法
void tree::non_InOrder(node *t) {
if (t == NULL) {
return;
}
node *p = t;
stack<node*> s;//借助栈s来实现中序遍历
while (p || !s.empty()) {
if(p) {
s.push(p);
p = p->lchild;
}
else{
p = s.top();
cout << p->data << endl;
s.pop();
p = p->rchild;
}
}
}
//后序遍历非递归方法,这个和中序还有前序有一些区别
void tree::non_PostOrder(node *t) {
if (t == NULL) {
return;
}
node *p=t, *pre=NULL;
stack<node*> s;
while (p || !s.empty()) {
if (p) {
s.push(p);
p = p->lchild;
}
else {
p = s.top();
if (p->rchild&&p->rchild != pre) {//此时右子树还未遍历过,需要进行遍历
p = p->rchild;
s.push(p);
p = p->lchild;
}
else {//当右子树已经遍历过时,此时应该进行节点的输出
s.pop();
cout << p->data<<endl;
pre= p;
p = NULL;
}
}
}
}
//前序遍历非递归算法
void tree::non_PreOrder(node *t) {
if (t == NULL) {
return;
}
node *p = t;
stack<node*> s;//和中序遍历一样的过程,只是顺序改变了
while (p || !s.empty()) {
if(p) {
cout << p->data << endl;
s.push(p);
p = p->lchild;
}
else {
p = s.top();
s.pop();
p = p->rchild;
}
}
}
int main()
{
tree T;
T.root = T.make_node(1,"root");
cout << "先序遍历的(非递归)结果是:" << endl;
T.non_PreOrder(T.root);
cout << "中序遍历的(非递归)结果是:" << endl;
T.non_InOrder(T.root);
cout << "后序遍历的(非递归)结果是:" << endl;
T.non_PostOrder(T.root);
return 0;
}
附上运行结果(包括递归方式):
明天将会更新二叉树最重要的层次遍历和二叉树的线索化内容