二叉树先序、中序、后序遍历的非递归实现

我们应该熟练掌握二叉树三大遍历的非递归算法实现,因为当树结点很多时,树的递归遍历就很低效了

下面程序都是先构建一个二叉搜索树,在二叉搜索树的基础上进行先序、中序、后序的非递归遍历

以下是二叉树后序遍历的非递归实现:

注意:二叉树遍历的非递归实现需要自己手动模拟以下它的遍历顺序,然后设计好出栈顺序

#include"stdafx.h"
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<stack>
using namespace std;
const int maxn = 1e3;
struct node {//结点
	int data;
	node* leftchild;
	node* rightchild;
	int flag;//结点标记
};
void insert(node* &root, int x, int flag) {//非递归插入
	//新建结点
	node* N = new node;
	N->data = x;
	N->leftchild = NULL;
	N->rightchild = NULL;
	N->flag = flag;
	//
	if (root == NULL) {
		root = N;
	}
	else {
		node* p = root;//工作指针
		node* pre = p;//p的前驱指针
		while (p != NULL) {
			pre = p;
			if (x < p->data) p = p->leftchild;
			else p = p->rightchild;
		}
		if (x < pre->data && pre->leftchild == NULL) pre->leftchild = N;
		else pre->rightchild = N;
	}
}
node* creat(int a[],int n) {//构建二叉搜索树
	node* root = NULL;
	for (int i = 0; i < n; i++) {
		insert(root, a[i], i);
	}
	return root;
}
void postorder(node* root) {//后序遍历的非递归算法
	stack<node*> s;
	bool vis[maxn] = { false };//标记是否被访问
	do {
		while (root != NULL) {
			s.push(root);
			root = root->leftchild;
		}
		root = s.top();
		if (root->rightchild != NULL) root = root->rightchild;
		else {
			while (root->rightchild == NULL || vis[root->rightchild->flag] == true) {
				cout << root->data << " ";//访问元素
				vis[root->flag] = true;//标记被访问
				s.pop();
				if (s.empty()) break;//pop后一定要检查栈是否为空,否则取不到栈顶元素
				root = s.top();
			}
			root = root->rightchild;
		}
	} while (!s.empty());
}
int main() {
	int n;
	cin >> n;
	int a[maxn];
	for (int i = 0; i < n; i++) {
		cin >> a[i];
	}
	node* root = creat(a, n);
	postorder(root);
	return 0;
}
-----------------------------------------------------------------------------------------
也可以将以上的非递归插入改成以下的递归插入
void insert(node* &root, int x, int flag) {//递归插入
	if (root == NULL) {
		root = new node;
		root->data = x;
		root->leftchild = NULL;
		root->rightchild = NULL;
		root->flag = flag;
		return;
	}
	else {
		if (x < root->data) {
			insert(root->leftchild, x,flag);
		}
		else {
			insert(root->rightchild, x,flag);
		}
	}
}

上面代码实现了二叉树后序遍历非递归算法,二叉树后序遍历非递归算法有一个很重要的特性:就是当访问某个结点时,栈中所保存的元素正好是这个结点的所有祖先。那么知道了这个特性,我们就很容易解决下面如下问题:

(1).当给定一个叶子结点,要求输出该叶子结点的所有祖先

(2).输出根结点到所有叶子结点的路径

(3).如果二叉树结点的值是数值,那么求每条路径上值之和,也可以利用二叉树后序遍历的非递归算法这个特性

等等等等

下面是中序遍历和先序遍历的非递归算法:

void inorder(node* root) {//中序遍历的非递归算法
	stack<node*> s;
	while (!s.empty() || root != NULL) {
		while (root != NULL) {
			s.push(root);
			root = root->leftchild;
		}
		root = s.top();
		s.pop();
		cout << root->data << " ";
		root = root->rightchild;
	}
}
-----------------------------------------------------------------------------------------
void preorder(node* root) {//先序遍历的非递归算法
	stack<node*> s;
	while (!s.empty() || root != NULL) {
		while (root != NULL) {
			cout << root->data << " ";
			s.push(root);
			root = root->leftchild;
		}
		root = s.top();
		s.pop();
		root = root->rightchild;
	}
}

猜你喜欢

转载自blog.csdn.net/qq_39034748/article/details/81811025