预备知识
二叉树的概念: 二叉树是一棵树,其中每个结点的儿子都不能多于两个。
二叉树的先序遍历:在遍历过程中,节点的访问顺序是:先访问根节点,然后遍历左子树,最后遍历右子树。对于任何给定的节点,它的左子树和右子树也按照同样的方式遍历。
二叉树的中序遍历:在遍历过程中,节点的访问顺序是:先遍历左子树,然后访问根结点,最后遍历右子树。对于任何给定的节点,它的左子树和右子树也按照同样的方式遍历。
二叉树的后序遍历: 在遍历过程中,节点的访问顺序是:先遍历左子树,然后遍历右子树, 最后访问根结点。对于任何给定的节点,它的左子树和右子树也按照同样的方式遍历。
树的声明
本文规定,每一颗树的根节点存储的一个正整数值
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
效果展示: