根据树的遍历结果创建一颗二叉树(c语言)

预备知识

二叉树的概念: 二叉树是一棵树,其中每个结点的儿子都不能多于两个。

二叉树的先序遍历:在遍历过程中,节点的访问顺序是:先访问根节点,然后遍历左子树,最后遍历右子树。对于任何给定的节点,它的左子树和右子树也按照同样的方式遍历。

二叉树的中序遍历:在遍历过程中,节点的访问顺序是:先遍历左子树,然后访问根结点,最后遍历右子树。对于任何给定的节点,它的左子树和右子树也按照同样的方式遍历。

二叉树的后序遍历: 在遍历过程中,节点的访问顺序是:先遍历左子树,然后遍历右子树, 最后访问根结点。对于任何给定的节点,它的左子树和右子树也按照同样的方式遍历。

树的声明

本文规定,每一颗树的根节点存储的一个正整数值

struct tree
{
	int value;
	struct tree* left;
	struct tree* right;
 };//by wqs

先序+中序创建二叉树

先序遍历结果用pre数组存储。

中序遍历结果用in数组存储。

接下来的函数将接受pre数组以及in数组以及一个整数n(表示树的结点个数),直接返回一颗创建好的二叉树。

struct tree* creattree(int* pre, int* in, int n)
{
	if (n <= 0) return NULL;//如果最终n小于0,说明树不存在,返回空树
	int* mid = in;
	while (*mid != *pre)
	{
		mid++;
	}
	//mid - in 能表示出中序遍历里面第一个结点与根节点的距离
	//在中序遍历里面找到根节点
	//根据规律揭示(本文不证明)
	//根节点左边的树的先序遍历结果为 pre + 1, 中序遍历结果为 in, 左边的树有mid - in 个结点
	//根节点右边的树的先序遍历结果为 pre + 1 + (mid - in), 中序遍历结果为 mid + 1, 右边的树有  n - (mid - in) - 1 个结点
	struct tree* p = (struct tree*)malloc(sizeof(struct tree));
	p->value = *mid;
	p->left = creattree(pre + 1, in, mid - in);
	p->right = creattree(pre + 1 + (mid - in), mid + 1, n - (mid - in) - 1);
	return p;
}//by wqs

后序+中序创建二叉树

后序结果用post数组存储。

中序结果用in数组存储。

接下来的函数将接受post数组以及in数组以及一个整数n(表示树的结点个数),直接返回一颗创建好的二叉树。

struct tree* creattree(int* post, int* in, int n)
{
	if (n <= 0) return NULL;//如果最终n小于0,说明树不存在,返回空树
	int* mid = in;
	while (*mid != *(post + n - 1))
	{
		mid++;//根节点在后序遍历的最后一个
	}
	//mid - in 能表示出中序遍历里面第一个结点与根节点的距离
	//在中序遍历里面找到根节点
	//根据规律揭示(本文不证明)
	//根节点左边的树的后序遍历结果为 post, 中序遍历结果为 in, 左边的树有mid - in 个结点
	//根节点右边的树的后序遍历结果为 post + (mid - in), 中序遍历结果为 mid + 1, 右边边的树有  n - (mid - in) - 1 个结点
	struct tree* p = (struct tree*)malloc(sizeof(struct tree));
	p->value = *mid;
	p->left = creattree(post, in, mid - in);
	p->right = creattree(post + (mid - in), mid + 1, n - (mid - in) - 1);
	return p;
}//by wqs

其实只要只要记住先序+中序创建二叉树,这种情况只是将pre + 1换成post

拓展法创建二叉树

前面的创建都需要中序遍历,这是因为中序遍历在知道了根节点的情况下,马上能得出左右子树。

其实还有一种创建树的方法不借助中序遍历结果,只需先序遍历结果。

但是只根据先序遍历结果无法创建一颗唯一的树(有时候可以),这是因为我们把空树忽略了,如果把空树也加入到遍历结果里面就能只凭一次遍历确定树的结构。

我们先前规定,每一个结点的值都是正整数,这样我们可以用-1来表示空树,下面的例子用**#**表示空树。
在这里插入图片描述

遍历结果为:ABD###C#E##

接下来的这个函数接受先序遍历并且加入空树的数组propre,函数直接返回一颗创建好的树,但是我们需要定义一个全局变量j,用来灵活引用propre数组

static int j = 0;//by wqs
struct tree* creattree(int* propre)
{
	if (propre[j] == -1)//值为-1返回空树
	{
		j++;
		return NULL;
	}
    struct tree* p = (struct tree*)malloc(sizeof(struct tree));
	p->value = propre[j++];
	p->left = creattree(propre);
	p->right = creattree(propre);
	return p;
}//by wqs

拓展法创建二叉树虽然只使用了一种遍历方式,但是其实并不比其他方法轻松。

其他代码

1,先序遍历结果打印

void preprint(struct tree* p)
{
	if (p == NULL) return;
	printf("%d ", p->value);
	preprint(p->left);
	preprint(p->right);
}//by wqs

2,中序遍历结果打印

void inprint(struct tree* p)
{
	if (p == NULL) return;
	inprint(p->left);
	printf("%d ", p->value);
	inprint(p->right);
}//by wqs

3,后序遍历结果打印

void postprint(struct tree* p)
{
	if (p == NULL) return;
	postprint(p->left);
	postprint(p->right);
	printf("%d ", p->value);
}//by wqs

4,打印一颗二叉树的三种遍历

void treestruct(struct tree* p)
{
	printf("先序遍历结果:");
	preprint(p);
	printf("\n");
	printf("中序遍历结果:");
	inprint(p);
	printf("\n");
	printf("后序遍历结果:");
	postprint(p);
	printf("\n");
}//by wqs

完整代码

#include<stdio.h>
#include<stdlib.h>
struct tree
{
	int value;
	struct tree* left;
	struct tree* right;
};
static int j = 0;
struct tree* creattree1(int*, int*, int);
struct tree* creattree2(int*, int*, int);
struct tree* creattree3(int*);
void preprint(struct tree*);
void inprint(struct tree*);
void postprint(struct tree*);
void treestruct(struct tree*);
int main()
{
	int n, pre[1000] = { 0 }, in[1000] = { 0 }, post[1000] = { 0 }, i = 0;
	printf("有多少个数:");
	scanf("%d", &n);
	printf("先序遍历结果:");
	for (i = 0; i < n; i++)
	{
		scanf("%d", &pre[i]);
	}
	printf("中序遍历结果:");
	for (i = 0; i < n; i++)
	{
		scanf("%d", &in[i]);
	}
	struct tree*  p = creattree1(pre, in, n);
	printf("二叉树创建成功\n");
	treestruct(p);
	printf("有多少个数:");
	scanf("%d", &n);
	printf("后序遍历结果:");
	for (i = 0; i < n; i++)
	{
		scanf("%d", &post[i]);
	}
	printf("中序遍历结果:");
	for (i = 0; i < n; i++)
	{
		scanf("%d", &in[i]);
	}
	p = creattree2(post, in, n);
	printf("二叉树创建成功\n");
	treestruct(p);
	printf("pro先序遍历一共多少个数(包括空树):");
	scanf("%d", &n);
	int propre[1000] = { 0 };
	printf("pro先序遍历结果:");
	for (i = 0; i < n; i++)
	{
		scanf("%d", &propre[i]);
	}
	p = creattree3(propre);
	printf("二叉树创建成功\n");
	treestruct(p);
	return 0;
}
struct tree* creattree1(int* pre, int* in, int n)
{
	if (n <= 0) return NULL;
	int* mid = in;
	while (*mid != *pre)
	{
		mid++;
	}
	struct tree* p = (struct tree*)malloc(sizeof(struct tree));
	p->value = *mid;
	p->left = creattree1(pre + 1, in, mid - in);
	p->right = creattree1(pre + 1 + (mid - in), mid + 1, n - (mid - in) - 1);
	return p;
}
struct tree* creattree2(int* post, int* in, int n)
{
	if (n <= 0) return NULL;
	int* mid = in;
	while (*mid != *(post + n - 1))
	{
		mid++;
	}
	struct tree* p = (struct tree*)malloc(sizeof(struct tree));
	p->value = *mid;
	p->left = creattree2(post, in, mid - in);
	p->right = creattree2(post + (mid - in), mid + 1, n - (mid - in) - 1);
	return p;
}
struct tree* creattree3(int* propre)
{
	if (propre[j] == -1)//值为-1返回空树
	{
		j++;
		return NULL;
	}
	struct tree* p = (struct tree*)malloc(sizeof(struct tree));
	p->value = propre[j++];
	p->left = creattree3(propre);
	p->right = creattree3(propre);
	return p;
}
void preprint(struct tree* p)
{
	if (p == NULL) return;
	printf("%d ", p->value);
	preprint(p->left);
	preprint(p->right);
}
void inprint(struct tree* p)
{
	if (p == NULL) return;
	inprint(p->left);
	printf("%d ", p->value);
	inprint(p->right);
}
void postprint(struct tree* p)
{
	if (p == NULL) return;
	postprint(p->left);
	postprint(p->right);
	printf("%d ", p->value);
}
void treestruct(struct tree* p)
{
	printf("先序遍历结果:");
	preprint(p);
	printf("\n");
	printf("中序遍历结果:");
	inprint(p);
	printf("\n");
	printf("后序遍历结果:");
	postprint(p);
	printf("\n");
}//by wqs

输入样例:

13
10 3 2 7 6 8 13 11 19 17 16 18 23
2 3 6 7 8 10 11 13 16 17 18 19 23
13
2 6 8 7 3 11 16 18 17 23 19 13 10
2 3 6 7 8 10 11 13 16 17 18 19 23
27
10 3 2 -1 -1 7 6 -1 -1 8 -1 -1 13 11 -1 -1 19 17 16 -1 -1 18 -1 -1 23 -1 -1

输出样例:

有多少个数:
先序遍历结果:
中序遍历结果:
二叉树创建成功
先序遍历结果:10 3 2 7 6 8 13 11 19 17 16 18 23
中序遍历结果:2 3 6 7 8 10 11 13 16 17 18 19 23
后序遍历结果:2 6 8 7 3 11 16 18 17 23 19 13 10
有多少个数:
后序遍历结果:
中序遍历结果:
二叉树创建成功
先序遍历结果:10 3 2 7 6 8 13 11 19 17 16 18 23
中序遍历结果:2 3 6 7 8 10 11 13 16 17 18 19 23
后序遍历结果:2 6 8 7 3 11 16 18 17 23 19 13 10
pro先序遍历一共多少个数(包括空树):
pro先序遍历结果:
二叉树创建成功
先序遍历结果:10 3 2 7 6 8 13 11 19 17 16 18 23
中序遍历结果:2 3 6 7 8 10 11 13 16 17 18 19 23
后序遍历结果:2 6 8 7 3 11 16 18 17 23 19 13 10

效果展示:
在这里插入图片描述

  • 8
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值