二叉树三种遍历方式,有先序,中序或者后序,中序恢复二叉树等操作

原创 2015年11月19日 16:41:02
//头文件
//BinaryTreeNode.h
#ifndef BINARYTREENODE_H
#define BINARYTREENODE_H
template<typename T>
class BinaryTreeNode{
public:
	T data;
	BinaryTreeNode<T>* leftChild;
	BinaryTreeNode<T>* rightChild;
	BinaryTreeNode(){

	}
	BinaryTreeNode(const T& val, BinaryTreeNode<T>* str, BinaryTreeNode<T>* ptr) :data(val), leftChild(str), rightChild(ptr){

	}
};
#endif
//BinaryTree.h
#ifndef BINARYTREE_H
#define BINARYTREE_H
#include"BinaryTreeNode.h"
#include<iostream>
#include<queue>
#include<stack>
#include<cstring>
using namespace std;
template<typename T>
class BinaryTree{
private:
	BinaryTreeNode<T>* root;
public:
	BinaryTree();
	~BinaryTree();
	//一下为二叉树的基本操作
	void creat();
	bool isEmpty();
	BinaryTreeNode<T>* getRoot();
	T reValue(BinaryTreeNode<T>* str)const;
	void reSet(BinaryTreeNode<T>* str, const T& val);
	void Deep()const;
	//输出操作
	void PrintInOrder(BinaryTreeNode<T>* str);
	void PrintLevelOrder();
	void PrintPostOrder(BinaryTreeNode<T>* str);
	//该函数是模拟先序,中序和后序,中序恢复出二叉树的操作
	void simulate();
private:
	//有中序序列和先序序列确定二叉树,递归形式的算法
	void DefineBinaryTree(BinaryTreeNode<T>* &str,char* preOrder,char* midOrder,int length);
	void DefineBinaryTree(char* preOrder, char* midOrder);
	//有后序序列,中序序列确定二叉树
	void DefineBinaryTreePost(BinaryTreeNode<T>* &str,char* postOrder,char* midOrder,int length);
	void DefineBinaryTreePost(char* postOrder, char* midOrder);
	//清空树
	void makeEmpty(BinaryTreeNode<T>* &str);
private:
	int deep(BinaryTreeNode<T>* str)const;
	void CreatBiTree(BinaryTreeNode<T>* &str);
	//非递归方法求树的深度
	int deepPrivate()const;
private:
	//该函数是用非递归方法,在给出先序和后序数列时,求出二叉树,该函数是为void DefineBinaryTree(char* preOrder, char* midOrder);
	//函数服务的
	int posChar(char ch, char* str);
};
template<typename T>
int BinaryTree<T>::posChar(char ch, char* str)
{
	if (strlen(str) == 0)
	{
		cout << "the char* is empty" << endl;
		exit(true);
	}
	int i = 0;
	while (str[i] != '\0')
	{
		if (ch == str[i])
		{
			return i;
		}
		i++;
	}
	return -1;
}
template<typename T>
void BinaryTree<T>::DefineBinaryTree(char* preOrder, char* midOrder)
{
	if (strlen(preOrder) == 0 || strlen(midOrder) == 0)
	{
		this->root = NULL;
		return;
	}
	//记录每个与先序中节点对应的后序中的节点的位置
	int pos;
	//position,node两个栈存放的是pos,和生成的每个节点
	stack<int>position;
	stack<BinaryTreeNode<T>*>node;
	//str,ptr用于生成节点
	BinaryTreeNode<T>* str = NULL;
	BinaryTreeNode<T>* ptr = NULL;
	str = new BinaryTreeNode<T>(preOrder[0], NULL, NULL);
	this->root = str;
	pos = posChar(preOrder[0], midOrder);
	position.push(pos);
	node.push(str);
	int i = 1;
	while (preOrder[i] != '\0')
	{
		pos = posChar(preOrder[i], midOrder);
		if (pos == -1)
		{
			cout << "the match is error" << endl;
			exit(true);
		}
		str = new BinaryTreeNode<T>(preOrder[i], NULL, NULL);
		if (pos < position.top())
		{
			//当num < position.top()时,则该节点是左节点
			ptr = node.top();
			ptr->leftChild = str;
			node.push(str);
			position.push(pos);
		}
		else
		{
			while (!position.empty() && pos > position.top())
			{
				ptr = node.top();
				position.pop();
				node.pop();
			}
			ptr->rightChild = str;
			node.push(str);
			position.push(pos);
		}
		i++;
	}
}
template<typename T>
void BinaryTree<T>::simulate()
{
	/*char preOrder[100];*/
	char postOrder[100];
	char midOrder[100];
	cout << "input the postOrder: ";
	/*cin >> preOrder;*/
	cin >> postOrder;
	//在这里对后序序列进行处理,将整个字符数组的顺序颠倒过来
	char str[100];
	int j = 0;
	int count = strlen(postOrder);
	for (int i = 0; i < count; j++, i++)
	{
		str[j] = postOrder[i];
	}
	str[j] = '\0';
	int i = 0;
	for (j = strlen(str) - 1; i < count, j >= 0; j--, i++)
	{
		postOrder[i] = str[j];
	}
	postOrder[i] = '\0';
	cout << "input the midOrder: ";
	cin >> midOrder;
	int length = strlen(midOrder);
	/*this->DefineBinaryTree(this->root,preOrder,midOrder,length);*/
	/*this->DefineBinaryTree(preOrder, midOrder);*/
	/*this->DefineBinaryTreePost(this->root, postOrder, midOrder,length);*/
	this->DefineBinaryTreePost(postOrder, midOrder);
}
template<typename T>
void BinaryTree<T>::DefineBinaryTree(BinaryTreeNode<T>* &str, char* preOrder, char* midOrder, int length)
{
	if (length == 0)
	{
		str = NULL;
		return;
	}
	str = new BinaryTreeNode<T>(*preOrder, NULL, NULL);
	char* pStr = strchr(midOrder, str->data);
	if (pStr == NULL)
	{
		cout << "the midOrder string is wrong" << endl;
		exit(true);
	}
	int leftTreeLength = strlen(midOrder) - strlen(pStr);
	int rightTreeLength = length - leftTreeLength - 1;
	DefineBinaryTree(str->leftChild, preOrder + 1, midOrder, leftTreeLength);
	DefineBinaryTree(str->rightChild, preOrder + leftTreeLength + 1, pStr + 1, rightTreeLength);
}
template<typename T>
void BinaryTree<T>::DefineBinaryTreePost(BinaryTreeNode<T>* &str, char* postOrder, char* midOrder, int length)
{
	if (length==0)
	{
		str = NULL;
		return;
	}
	str = new BinaryTreeNode<T>(*postOrder, NULL, NULL);
	char* pStr = strchr(midOrder, str->data);
	if (pStr == NULL)
	{
		cout << "the midOrder is wrong" << endl;
		exit(true);
	}
	//这里的字符串处理有错误
	int leftLength = strlen(midOrder) - strlen(pStr);
	int rightLength = length - leftLength - 1;
	DefineBinaryTreePost(str->leftChild, postOrder + rightLength + 1, midOrder, leftLength);
	DefineBinaryTreePost(str->rightChild, postOrder + 1, midOrder + leftLength + 1, rightLength);
}
template<typename T>
void BinaryTree<T>::DefineBinaryTreePost(char* postOrder, char* midOrder)
{
	//在该函数中的postOrder序列是顺序已经被颠倒之后的序列
	if (strlen(postOrder) == 0 || strlen(midOrder) == 0)
	{
		this->root = NULL;
		return;
	}
	int pos;
	stack<int>position;
	stack<BinaryTreeNode<T>*>node;
	BinaryTreeNode<T>* str = NULL;
	BinaryTreeNode<T>* ptr = NULL;
	str = new BinaryTreeNode<T>(postOrder[0], NULL, NULL);
	this->root = str;
	pos = posChar(str->data, midOrder);
	node.push(str);
	position.push(pos);
	int i = 1;
	while (postOrder[i] != '\0')
	{
		pos = posChar(postOrder[i], midOrder);
		if (pos == -1)
		{
			cout << "the midOrder is error" << endl;
			exit(true);
		}
		str = new BinaryTreeNode<T>(postOrder[i], NULL, NULL);
		if (pos < position.top())
		{
			ptr = node.top();
			ptr->leftChild = str;
			node.push(str);
			position.push(pos);
		}
		else
		{
			while (!position.empty() && pos>position.top())
			{
				ptr = node.top();
				node.pop();
				position.pop();
			}
			ptr->rightChild = str;
			node.push(str);
			position.push(pos);
		}
		i++;
	}
}
template<typename T>
int BinaryTree<T>::deepPrivate()const
{
	if (this->root == NULL)
		return 0;
	BinaryTreeNode<T>* p = this->root;
	queue<BinaryTreeNode<T>*>que;
	que.push(p);
	int deepth = 0;
	while (!que.empty())
	{
		deepth++;
		//每次在循环开始之前,都要获得cur=0,和curQueSize的值
		//curQueSize记录了每一层中的节点数目,当所有的这一层的节点的左右孩子全部都进入
		//队列后退出循环
		int cur = 0;
		int curQueSize = que.size();
		while (cur < curQueSize)
		{
			cur++;
			//每次都要保证在队列中的节点为同一层的节点
			p = que.front();
			que.pop();
			if (p->leftChild)
				que.push(p->leftChild);
			if (p->rightChild)
				que.push(p->rightChild);
		}
	}
	return deepth;
}
template<typename T>
void BinaryTree<T>::Deep()const
{
	cout << "the deep is " << this->deepPrivate() << " of the tree" << endl;
}
template<typename T>
int BinaryTree<T>::deep(BinaryTreeNode<T>* str)const
{
	if (str == NULL)
		return 0;
	int h1, h2;
	h1 = deep(str->leftChild);
	h2 = deep(str->rightChild);
	return h1 > h2 ? h1 + 1 : h2 + 1;
}
template<typename T>
bool BinaryTree<T>::isEmpty()
{
	if (this->root == NULL)
		return true;
	return false;
}
template<typename T>
BinaryTree<T>::BinaryTree()
{
	this->root = NULL;
}
template<typename T>
BinaryTree<T>::~BinaryTree()
{
	this->makeEmpty(this->root);
}
template<typename T>
BinaryTreeNode<T>* BinaryTree<T>::getRoot()
{
	if (this->isEmpty())
	{
		cout << "the tree is empty" << endl;
		exit(true);
	}
	return this->root;
}
template<typename T>
T BinaryTree<T>::reValue(BinaryTreeNode<T>* str)const
{
	if (str == NULL)
	{
		cout << "the point is null" << endl;
		exit(true);
	}
	return str->data;
}
template<typename T>
void BinaryTree<T>::reSet(BinaryTreeNode<T>* str, const T& val)
{
	if (str == NULL)
	{
		cout << "the point is null" << endl;
		exit(true);
	}
	str->data = val;
}
template<typename T>
void BinaryTree<T>::makeEmpty(BinaryTreeNode<T>* &str)
{
	if (str)
	{
		makeEmpty(str->leftChild);
		makeEmpty(str->rightChild);
		delete str;
	}
	str = NULL;
}
template<typename T>
void BinaryTree<T>::creat()
{
	this->CreatBiTree(root);
}
template<typename T>
void BinaryTree<T>::CreatBiTree(BinaryTreeNode<T>* &str)
{
	T value;
	if (root == NULL)
	{
		cout << "the root data is: ";
	}
	cin >> value;
	if (value == '#')
	{
		str = NULL;
		return;
	}
	else
	{
		str = new BinaryTreeNode<T>(value, NULL, NULL);
		cout << "input the " << str->data << " leftchild: ";
		CreatBiTree(str->leftChild);
		cout << "input the " << str->data << " rightchild: ";
		CreatBiTree(str->rightChild);
	}
}
template<typename T>
void BinaryTree<T>::PrintInOrder(BinaryTreeNode<T>* str)
{
	if (str != NULL)
	{
		PrintInOrder(str->leftChild);
		cout << str->data << " ";
		PrintInOrder(str->rightChild);
	}
	else
		return;
}
template<typename T>
void BinaryTree<T>::PrintLevelOrder()
{
	BinaryTreeNode<T>* p = this->root;
	queue<BinaryTreeNode<T>*>nodeQue;
	if (p != NULL)
		nodeQue.push(p);
	while (!nodeQue.empty())
	{
		p = nodeQue.front();
		nodeQue.pop();
		cout << p->data << " ";
		if (p->leftChild)
			nodeQue.push(p->leftChild);
		if (p->rightChild)
			nodeQue.push(p->rightChild);
	}
	cout << endl;
}
template<typename T>
void BinaryTree<T>::PrintPostOrder(BinaryTreeNode<T>* str)
{
	if (str != NULL)
	{
		PrintPostOrder(str->leftChild);
		PrintPostOrder(str->rightChild);
		cout << str->data << " ";
	}
}
#endif
//主函数
#include"BinaryTree.h"
int main(int argc, char argv[])
{
	BinaryTree<char>tree;
	tree.creat();
	tree.PrintInOrder(tree.getRoot());
	cout << endl;
	tree.PrintLevelOrder();
	tree.PrintPostOrder(tree.getRoot());
	cout << endl;
	tree.Deep();
	tree.simulate();
	tree.PrintPostOrder(tree.getRoot());
	cout << endl;
	tree.Deep();
	return 0;
}

根据前序和中序遍历还原二叉树后序遍历(hihocoder 1049)

时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 在参与过了美食节之后,小Hi和小Ho在别的地方又玩耍了一阵子,在这个过程中,小Ho得到了一个非常有意思的玩具—...
  • Z_zhangyinqian
  • Z_zhangyinqian
  • 2015年12月02日 10:55
  • 775

根据二叉树前序、中序遍历还原二叉树

在学习二叉树遍历的时候我们学习了三种遍历方法 前序 中序 后序 同时我们知道给定前序和中序、中序和后序我们可以还原二叉树, 记得当时只是在纸上画了一画。现在把当时的想法完成。 给定前序和中序还原...
  • w823626691
  • w823626691
  • 2014年04月07日 14:02
  • 1444

从前序+中序或者后序+中序序列中恢复二叉树过程

给出前序遍历和中序遍历,如何绘制出二叉树: 如果给出遍历产生的一串字符,不容易确定各个字符在树中的具体位置,因而需要两个遍历串相结合才能画出一棵二叉树。 如,给出前序遍历ADFGHKLPQRWZ,...
  • dalong277
  • dalong277
  • 2016年04月26日 11:18
  • 1652

如何根据前序、中序、后序遍历还原二叉树

面试题目或多或少会出现这样的选择题或者简答题: 首先我们得知道概念: 前序遍历:先访问当前节点,再访问当前节点的左子树,最后访问当前节点的右子树。对于二叉树,深度遍历与此同。规律:根在前;子树在根...
  • yanerhao
  • yanerhao
  • 2015年04月21日 20:49
  • 5272

根据二叉树的中序和后序还原二叉树

P:终点时要明白二叉树的几种遍历方法以及规律; 先序:中左右。 中序:左中右。 后序:左右中。 上面的左右皆为中的子树,所以优势具有二叉树的特性,那么我们就可以递归还原树了; 这里是一个二叉树还原及求...
  • KIJamesQi
  • KIJamesQi
  • 2015年09月20日 10:47
  • 819

数据结构与算法简记:通过前序中序或中序后序构建二叉树

上次记录了广义表生成二叉树的过程,我们也可以通过前序和中序,或者中序和后序,来构建一棵唯一的二叉树。 还是同样的图,它的前序,中序,后序遍历序列分别是: pre: ABCDEF in: CBD...
  • liuhe688
  • liuhe688
  • 2016年07月08日 12:10
  • 1980

通过先序和中序或后序和中序画出二叉树

1.通过先序和中序得出二叉树 先序:EBADCFHGIKJ 中序:ABCDEFGHIJK 基本思路:(递归) 1.从先序中找第一个节点,在中序中找到该节点,把树分为了左右子树....
  • whoamiyang
  • whoamiyang
  • 2016年03月13日 08:59
  • 754

根据先序和中序还原(重建)一个二叉树

package tree.BinaryTree;import java.util.Arrays;/** * 根据先序和中序还原一个二叉树 * * @author yuzhiyun * */...
  • yuzhiyun3536
  • yuzhiyun3536
  • 2016年12月05日 16:06
  • 481

二叉树前序,中序转后序

由二叉树的前序和中序如何得到二叉树的后序呢?要给出答案,首先得明白什么是前序、中序、后序。 二叉树前序:遍历顺序为,根节点、左子树、右子树;中序:遍历顺序为,左子树、根节点、右子树;后序:遍历顺...
  • wu_cai_
  • wu_cai_
  • 2016年09月17日 11:24
  • 539

二叉树前序、中序、后序遍历的相互求法

二叉树前序、中序、后序遍历的相互求法       二叉树是数据结构中常被问到的相关知识点,也是我们需要了解的一个知识点,那今天来总结一下二叉树的前序、中序、后序遍历的相互求法,即如果知道两个...
  • u014536527
  • u014536527
  • 2016年03月30日 02:45
  • 5775
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:二叉树三种遍历方式,有先序,中序或者后序,中序恢复二叉树等操作
举报原因:
原因补充:

(最多只允许输入30个字)