数据结构总目录
根据先序和中序构建二叉树
1. 建立过程图解
假设我们已知先序序列《ABCDEFG》和中序序列《CDBAEFG》,则我们可以构建出如下一颗二叉树
构建规则分析
(1)已知先序序列(根、左、右)和中序序列(左、根、右)的遍历顺序
(2)由先序序列的第一个数据是根节点,可得中序序列中的根节点位置
(3)由中序根节点位置,可确定左右两边的子序列分别为左子树和右子树序列
2. 区间计算
具体左子树和右子树的划分计算如下:
第一步:由先序序列可知
- 第一个结点必定为根结点,而后可以在中序序列中查找出根结点的位置root
第二步:根据中序结点的根节点位置root,可得
- 中序左子树的区间范围为【L2,root - 1】,中序右子树的区间范围为【root + 1,R2】
- 中序左子树区间长度 :X= root - L2,中序右子树区间长度:Y = R2 - root
第三步:根据中序序列的左子树和右子树区间可得
- X = 先序左子树区间长度 = 中序左子树区间长度 = root - L2
- Y = 先序右子树区间长度 = 中序右子树区间长度 = R2 - root
- 先序左子树区间为【L1 + 1,L1 + 左子树区间长度】 = 【L1 + 1,L1 + (root - L2)】
- 先序右子树区间为【R1 - 左子树区间长度 + 1,R1】 = 【R1 - (R2 - root) + 1,R1】
3. 源代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef char DataType;
typedef struct BiTNode
{
DataType data;
struct BiTNode *lchild, *rchild;
}LinkBiTree;
// 根据先序、中序序列构建二叉树
void CreateBiTree(LinkBiTree **T, char *PreStr, char *InStr, int L1, int R1, int L2, int R2)
{
/* int i;
printf("先序序列:");
for (i = L1; i <= R1; i++){printf("%c ", PreStr[i]);}
printf("\n中序序列:");
for (i = L2; i <= R2; i++){printf("%c ", InStr[i]);}
printf("\n"); */
// 创建新的结点
(*T) = (LinkBiTree *)malloc(sizeof(LinkBiTree));
// 新结点数据为设置 先序序列 的第一个数据,即根节点数据
(*T)->data = PreStr[L1];
// 根据先序第一个元素为根结点元素,寻找中序序列中的根结点位置
int root;
for (root = 0; root <= R2; root++)
{
if (PreStr[L1] == InStr[root])
{
printf("先序序列根节点(%c)在中序的位置 = %d\n", PreStr[L1], root);
break;
}
}
// 判断中序序列中<root>的左边是否存在左子序列
if (root - L2 != 0)
{
// 划分两个区间,先序序列左子树区间 和 中序序列左子树区间,递归构建左子树
/* printf("\t划分先序序列的左子树区间:[%d, %d] = > ", L1 + 1, L1 + (root - L2));
for (i = L1 + 1; i <= L1 + (root - L2); i++){printf("%c ", PreStr[i]);}
printf("\n");
printf("\t划分中序序列的左子树区间:[%d, %d] = > ", L2, root - 1);
for (i = L2; i <= root - 1; i++){printf("%c ", InStr[i]);}
printf("\n"); */
CreateBiTree(&(*T)->lchild, PreStr, InStr, L1 + 1, L1 + (root - L2), L2, root - 1);
}
else
{
(*T)->lchild = NULL;
}
// 判断中序序列中<root>的右边是否存在右子序列
if (R2 - root != 0)
{
// 划分两个区间,先序序列右子树区间 和 中序序列右子树区间,递归构建右子树
/* printf("\t划分先序序列的右子树区间:[%d, %d] = > ", L1 + 1, L1 + (root - L2));
for (i = R1 - (R2 - root) + 1; i <= R1; i++){printf("%c ", PreStr[i]);}
printf("\n");
printf("\t划分中序序列的右子树区间:[%d, %d] = > ", L2, root - 1);
for (i = root + 1; i <= R2; i++){printf("%c ", InStr[i]);}
printf("\n"); */
CreateBiTree(&(*T)->rchild, PreStr, InStr, R1 - (R2 - root) + 1, R1, root + 1, R2);
}
else
{
(*T)->rchild = NULL;
}
}
// 后序遍历二叉树
void PostOrderTraverse(LinkBiTree *T)
{
if (T)
{
PostOrderTraverse(T->lchild);
PostOrderTraverse(T->rchild);
printf("%c ", T->data);
}
}
int main()
{
char PreStr[30], InStr[30];
// 参考用例:ABCDEFG
printf("请输入先序序列:"); //测试用例:ABDEHJKLMNCFGI
scanf("%s", PreStr);
//参考用例:CBDAEFG
printf("请输入中序序列:"); //测试用例:DBJHLKMNEAFCGI
scanf("%s", InStr);
int len1 = strlen(PreStr);
int len2 = strlen(InStr);
LinkBiTree *T;
CreateBiTree(&T, PreStr, InStr, 0, len1 - 1, 0, len2 - 1);
printf("后序遍历二叉树:");
PostOrderTraverse(T);
printf("\n");
return 0;
}