二叉树的非递归算法(C++实现)

接着上面一篇博客,我们开始叙述有关二叉树的非递归遍历的实现。

这里我们附上上一篇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;
}

附上运行结果(包括递归方式):

《二叉树的非递归算法(C++实现)》

明天将会更新二叉树最重要的层次遍历和二叉树的线索化内容

    原文作者:递归算法
    原文地址: https://blog.csdn.net/weixin_36997518/article/details/81396608
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞