数据结构之树

二叉树

逻辑结构与内存结构

结构实现

二叉树

  • 建立二叉树
  • 先序遍历(递归与非递归实现)
  • 中序遍历(递归与非递归实现)
  • 后序遍历(递归与非递归实现)
  • 层序遍历
  • 求树宽(递归与非递归实现)
  • 求树深(递归与非递归实现)
  • 结点最远距离
  • 先序数组和中序数组建树
  • 中序数组和后序数组建树
#include "队列栈.h"
#include<iostream>

using namespace std;

typedef char Elemtypes;
typedef struct node
{
	Elemtypes data;
	struct node* Lchild, * Rchild;
}BiNode, * BiTree;
//生成树
void CreatTree(BiTree& root);
//访问结点数据
void Visit(BiTree root);
//先序遍历(递归)
void PreOrder(BiTree root);
//中序遍历(递归)
void InOrder(BiTree root);
//后序遍历(递归)
void PostOrder(BiTree root);
//先序遍历(非递归)
void stack_PreOrder(BiTree root);
//中序遍历(非递归)
void stack_InOrder(BiTree root);
//后序遍历(非递归)
void stack_PostOrder(BiTree root);
//层序遍历(队列实现)
void FloorOrder(BiTree root);
//先序中序建树
void Pre_In_Tree(char* Pre, char* In, BiTree& root, int len);
//后序中序建树
void Post_In_Tree(char* Post, char* In, BiTree& root, int len);
//int main()
//{
//	BiTree root = NULL;
//	//CreatTree(root);
//	char post[100], in[100];
//	cin >> in >> post;
//	int len = strlen(in);
//	//Pre_In_Tree(pre, in, root, len);
//	Post_In_Tree(post, in, root, len);
//	PostOrder(root);
//	return 0;
//}
//生成树
void CreatTree(BiTree& root)
{
	char data;
	cin >> data;							//输入数据
	if (data == '#')
	{
		return;								//如果输入#则该树分支结束
	}
	root = new BiNode;
	root->data = data;
	root->Lchild = root->Rchild = NULL;
	CreatTree(root->Lchild);				//递归生成该结点左子树
	CreatTree(root->Rchild);				//递归生成该结点右子树
}
//访问结点数据
void Visit(BiTree root)
{
	cout << root->data << " ";
}
//先序遍历(递归)
void PreOrder(BiTree root)
{
	if (root == NULL)					//为NULL说明已经到叶子的左右结点了
		return;
	Visit(root);
	PreOrder(root->Lchild);				//递归访问左子树
	PreOrder(root->Rchild);				//递归访问右子树
}
//中序遍历(递归)
void InOrder(BiTree root)
{
	if (root == NULL)
		return;
	InOrder(root->Lchild);				//递归访问左子树
	Visit(root);
	InOrder(root->Rchild);				//递归访问右子树
}
//后序遍历(递归)
void PostOrder(BiTree root)
{
	if (root == NULL)
		return;
	PostOrder(root->Lchild);			//递归访问左子树
	PostOrder(root->Rchild);			//递归访问右子树
	Visit(root);
}
//先序遍历(非递归)
void stack_PreOrder(BiTree root)
{
	BiTree p = root;
	Stack s;
	InitStack(s);
	Push(s, p);							//根结点入栈
	while (s.top != s.bot)				//循环条件为栈非空
	{
		Pop(s, p);						//出栈访问
		Visit(p);
		if (p->Rchild != NULL)			//如果结点右子树不为空则入栈
			Push(s, p->Rchild);	
		if (p->Lchild != NULL)			//如果结点左子树不为空则入栈
			Push(s, p->Lchild);
	}
}
//中序遍历(非递归)
void stack_InOrder(BiTree root)
{
	BiTree p = root;
	Stack s;
	InitStack(s);
	while (p != NULL || s.top != s.bot)		
	{
		if (p!= NULL)					//如果结点不为空则入栈并进入到左节点
		{
			Push(s, p);
			p = p->Lchild;
		}
		else
		{								//如果结点为空则说明左子树走到底了
			Pop(s, p);					//出栈并访问
			cout << p->data << " ";
			p = p->Rchild;				//进入右子树
		}
	}
}
//后序遍历(非递归)
void stack_PostOrder(BiTree root)
{
	BiTree p = root, r = NULL;			//r用于记住上一次访问的结点
	Stack s;
	InitStack(s);
	while (p != NULL || s.bot != s.top)
	{
		if (p != NULL)					//结点不为空则入栈并进入左节点
		{
			Push(s, p);
			p = p->Lchild;
		}
		else
		{
			p = *(s.top - 1);	//获得栈顶元素
			if (p->Rchild != NULL && p->Rchild != r)	//如果右节点不为空且没有访问过则进入右节点
			{
				p = p->Rchild;
			}
			else
			{								//如果访问过或为空
				Pop(s, p);					//出栈并访问
				Visit(p);	
				r = p;						//将r标记到访问过的p结点
				p = NULL;					//再将p置空(如果不置空将会进入到死循环中 p(入栈)->p左节点-> p ->p 右节点 ->p
			}
		}
	}
}
//层序遍历
void FloorOrder(BiTree root)
{
	BiTree p = root;
	Queue q;
	InitQueue(q);
	EnQueue(q, p);
	int h = 0, w = 0;
	while (q.front < q.rear)
	{
		int i = q.rear - q.front;		//i为层宽
		w = w < i ? i : w;				//w用于记住树的最大层宽
		for (int j = 0; j < i; j++)		//每一个队列中的结点都会对左右结点判断是否为空
		{
			DeQueue(q, p);
			Visit(p);
			if (p->Lchild != NULL)
				EnQueue(q, p->Lchild);	//左节点入队列
			if (p->Rchild != NULL)
				EnQueue(q, p->Rchild);	//右节点入队列
		}
		h++;							//树高+1
	}
	cout << endl << h << " " << w << endl;
}
//先序中序建树
void Pre_In_Tree(char* Pre, char* In, BiTree& root, int len)
{
	if (len == 0)						//递归数组长度为0时已经存储完了,因此退出
		return;
	root = new BiNode;
	root->Rchild = root->Lchild = NULL;
	root->data = *Pre;					//Pre先序数组的第一个数据是根结点
	int i;
	for (i = 0; i < len; i++)			//遍历In中序数组找到根结点,记住所在位置i
	{
		if (*Pre == In[i])
			break;
	}
	Pre_In_Tree(Pre + 1, In, root->Lchild, i);//递归找左子树,左子树在根结点左边,长度为i
	Pre_In_Tree(Pre + i + 1, In + i + 1, root->Rchild, len - i - 1);//递归找右子树,在根结点右边
													//长度为len-i-1
}

//后序中序建树
void Post_In_Tree(char* Post, char* In, BiTree& root, int len)
{
	if (len == 0)
		return;
	root = new BiNode;
	root->Rchild = root->Lchild = NULL;
	root->data = *(Post + len - 1);				//后序数组的最后结点为根结点
	int i = 0;
	for (i; i < len; i++)
	{
		if (Post[len - 1] == In[i])				//遍历找到中序数组中的根节点位置i
			break;
	}
	Post_In_Tree(Post, In, root->Lchild, i);	//前i个元素为左子树
	Post_In_Tree(Post + i, In + i + 1, root->Rchild, len - i - 1);//后len-i-个元素为右子树
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值