用中序序列和前序序列构造二叉树
让我们考虑以下遍历结果:
中序序列:DBEAFC
前序序列:ABDECF
在前序序列中, 最左边的元素是树的根。对于上面给定的序列,我们知道 ‘A’ 是树的根。
然后在中序序列中找到 ‘A’ 的位置,我们发现所有位于 ‘A’ 左边的元素存在于树的左子树,
位于 ‘A’ 右边的元素存在于树的右子树。
A / \ / \ D B E F C
我们递归地按照上述步骤来构建整棵树。
A / \ / \ B C / \ / / \ / D E F
Algorithm
定义函数 buildTree()
- 在前序序列中取出一个元素。增加前序序列索引变量,以便在下次递归调用过程中取下一个元素。
- 用取出元素作为数据域创建一个新节点 tNode。
- 在中序序列中查找取出元素的索引,赋值给 inIndex。
- 用 inIndex 之前的元素递归调用 buildTree()创建树,并将其作为 tNode 的左子树。
- 用 inIndex 之前的元素递归调用 buildTree()创建树,并将其作为 tNode 的右子树。
- 返回 tNode
#include <stdio.h> #include <stdlib.h> /*
* 一个二叉树结点包括数据域,和指向左子树与右子树的指针
*/ struct node { char data; struct node* left; struct node* right; }; int search(char arr[], int strt, int end, char value); struct node* newNode(char data);
/*
* 前序序列索引
*/
int preIndex = 0;
/*
* 利用中序序列 in[] 和前序序列 pre[] 递归地构造一棵大小为 len 的二叉树
* inStart 和 inEnd 的初始值应当为 0 和 len-1 .
* 当中序序列和前序序列不能构造一棵二叉树时,此函数不会左任何检测。
*/ struct node* buildTree(char in[], char pre[], int inStrt, int inEnd) { if (inStrt > inEnd) return NULL; // 利用索引 preIndex 从前序序列中取出一个元素,并利用此元素创建一个二叉树结点 // 最后索引值 preIndex 加 1 struct node* tNode = newNode(pre[preIndex++]); // 如果此结点没有孩子则返回 if (inStrt == inEnd) return tNode; //否则在中序序列中找到此元素的索引 int inIndex = search(in, inStrt, inEnd, tNode->data); // 利用中序索引构造左子树与右子树 tNode->left = buildTree(in, pre, inStrt, inIndex - 1); tNode->right = buildTree(in, pre, inIndex + 1, inEnd); return tNode; } /*
* 功能函数 * 此函数的功能是在数组 arr[start...end] 中查找值 value 的索引 * 此函数默认 value 在 arr[start...end] 中出现
*/ int search(char arr[], int strt, int end, char value) { int i; for (i = strt; i <= end; i++) { if (arr[i] == value) return i; } } /*
* 辅助函数
* 利用给定的数据域 data 分配一个新结点,该节点的 left 和 right 域均为 NULL
* 并返回指向该结点的指针
*/ struct node* newNode(char data) { struct node* node = (struct node*)malloc(sizeof(struct node)); node->data = data; node->left = NULL; node->right = NULL; return (node); } /*
* 为了验证 buildTree()
*/ void printInorder(struct node* node) { if (node == NULL) return; printInorder(node->left); printf("%c ", node->data); printInorder(node->right); } int main() { char in[] = { 'D', 'B', 'E', 'A', 'F', 'C' }; char pre[] = { 'A', 'B', 'D', 'E', 'C', 'F' }; int len = sizeof(in) / sizeof(in[0]); struct node* root = buildTree(in, pre, 0, len - 1); printInorder(root); getchar(); }