数据结构之树
树#
二叉树#
逻辑结构与内存结构#
结构实现#
二叉树#
- 建立二叉树
- 先序遍历(递归与非递归实现)
- 中序遍历(递归与非递归实现)
- 后序遍历(递归与非递归实现)
- 层序遍历
- 求树宽(递归与非递归实现)
- 求树深(递归与非递归实现)
- 结点最远距离
- 先序数组和中序数组建树
- 中序数组和后序数组建树
#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-个元素为右子树
}
作者:墨鱼-yyyl
出处:https://www.cnblogs.com/moyu-yyyl/p/18009722
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~