数据结构:二叉树的各种遍历算法实现

题目:

实现上述二叉树的先序、中序和后序遍历的递归和非递归算法;

思路:

(1) 前序遍历递归算法:利用递归,先输出结点,在搜索左子树,最后搜索右子树
(2) 中序遍历递归算法:利用递归,先搜索左子树,再输出结点,最后搜索右子树
(3) 后序遍历递归算法:利用递归,先搜索左子树,在搜索右子树,最后输出结点
(4) 前序遍历非递归算法:建立一个栈来存储树结点,首先将首根结点放入栈,接着,利用循环,循环中获取栈顶元素并弹出,依次放入栈顶元素的右子树和左子树(栈后进先出,前序遍历先左后右,入栈先右后左),直到栈空即可
(5) 中序遍历非递归算法:建立一个栈来存储树结点,建立循环,将结点的左子树放入栈,当结点不存在左子树时,将临时结点初始化为栈顶元素,弹出栈顶元素,将临时结点变为其右子树即可
(6) 后序遍历非递归算法:后序遍历利用栈需要记录结点使用次数,一个结点只有使用了两次的时候,左右子树才均以使用,所以利用map来记录结点使用次数,首先建立循环,找左子树并入栈,入栈结点使用次数为1,当左子树找完时,临时结点设置为栈顶元素,如果该结点使用次数为2,直接输出结点值并弹出栈,否则将访问其右子树,将其访问次数置为2。

代码块:

#include "pch.h"
#include <iostream>
#include<stack>
#include<set>
#include<map>
using namespace std;
struct Btree {
	char data;
	Btree *lchild;
	Btree *rchild;
};
void create(Btree*&root)//创建二叉树
{
	char data;
	cin >> data;
	root = new Btree;
	if (data == '#') root = NULL;
	if (root!=NULL)
	{
		root->data = data;
		cout<<"请输入" <<data<< "的左子树:" << endl; create(root->lchild);
		cout << "请输入" << data << "的右子树:" << endl; create(root->rchild);
	}
}
void preorder(Btree*&root)//前序遍历递归算法
{
	if(root!=NULL)
	{
		cout << root->data << "\t";
		if(root->lchild)preorder(root->lchild);
		if (root->rchild)preorder(root->rchild);
	}
}
void ldr(Btree *&tree)//中序遍历递归算法
{
	if (tree != NULL)
	{
		if(tree->lchild)ldr(tree->lchild);
		cout << tree->data << '\t';
		if (tree->rchild)ldr(tree->rchild);
	}
}
void lrd(Btree *&tree)//后序遍历递归算法
{
	if (tree != NULL)
	{
		if (tree->lchild)lrd(tree->lchild);
		if (tree->rchild)lrd(tree->rchild);
		cout << tree->data << '\t';
	}
}
void NORecursionprd(Btree *&tree){//前序非递归算法
	Btree *p = tree;
	stack<Btree*> s;
	s.push(tree);
	while (!s.empty())
	{
		p = s.top();//获取栈顶元素
		s.pop();//弹出栈顶元素
		cout << p->data << '\t';
		if (p->rchild) s.push(p->rchild);//先将右子树入栈
		if (p->lchild)s.push(p->lchild);//再将左子树入栈,栈后进先出,符合前序遍历规则
	}
}
void NORecursionldr(Btree*&tree)//中序遍历非递归算法
{
	stack<Btree*> s;//建立栈
	Btree *p = tree;
	while (p != NULL || !s.empty()) {
		while (p != NULL) {//依次将每个结点的左子树放入栈
			s.push(p);
			p = p->lchild;
		}
		if (!s.empty()) {//在栈非空时找到栈顶元素的右子树
			p = s.top();
			s.pop();
			cout << p->data<<'\t';//弹出栈顶元素,实现中序遍历
			p = p->rchild;
		}
	}
}
void NORecursionlrd(Btree *&tree)
{
	map<Btree*, int>judge;//利用map记录访问次数
	stack<Btree*>s;//利用栈来模拟后序遍历
	Btree*p=tree;//临时保存结点
	while (p != NULL || !s.empty())
	{
		if(p!=NULL)//如果结点不为空,一直往下找其左子树
		{
			s.push(p);
			p = p->lchild;
			judge[p] = 1;
		}
		else {//结点为空
			p = s.top();//取栈顶元素
			if (judge[p] == 2) {//若访问过两次,说明左右子树均已经访问,直接输出其数据即可
				s.pop();
				cout << p->data << '\t';
				p = NULL;
			}
			else {//否则将访问其右子树,将其访问次数置为2
				judge[p] = 2;
				p = p->rchild;
			}
		}
		
	}
}

int main()
{
	Btree*tree=new Btree;
	cout << "请输入首根结点数据:";
	if (tree == NULL) cout << "树为空树!\n";
	else{
		create(tree);
		cout << "该树递归前序遍历的结果为:\n";
		preorder(tree);
		cout<<endl << "该树非递归前序遍历的结果为:\n";
		NORecursionprd(tree);
		cout << endl << "该树递归中序遍历的结果为:\n";
		ldr(tree);
		cout << endl << "该树非递归中序遍历的结果为:\n";
		NORecursionldr(tree);
		cout << endl << "该树递归后序遍历的结果为:\n";
		lrd(tree);
		cout << endl << "该树非递归后序遍历的结果为:\n";
		NORecursionlrd(tree);
	}
}

效果图:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

发布了330 篇原创文章 · 获赞 13 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_43981315/article/details/103914862
今日推荐