说明:
给定输入一棵二叉树的前序遍历和中序遍历数组。利用此重新建立二叉树。注意输入不包含相同的键值,否则情况复杂得多。
思路:
由定义,前序遍历的第一个记录总是根节点,而这个键值在中序遍历时,将中序遍历的数组分成两部分,分别对应这个根节点的左右两子树。同时,前序遍历数组跟在节点后的数组也分成两部分,其中前面对应左子树的前序遍历,后面部分对应右子树的前序遍历。
于是,我们联想到分治法,利用递归,每次找到根节点,然后利用一个定位函数在中序遍历数组中找到位置划分,再将新的划分重新划分两个数组,并递归进行建立二叉树。
代码实例:
#include<iostream>
using namespace std;
typedef struct Node{
int key;
Node *left;
Node *right;
}DNode;
int find(int key, int *start, int endloc){
//给定键值查找其在链表中的相对位置。
for (int i = 0; i <= endloc; i++){
if (*(start + i) == key) return i;
}
}
DNode *creat(int *pre,int *in,int endloc){
//to do sth. for not valid input
//if (!pre) return NULL;
DNode *node = new DNode;
node->key = *pre;
node->left = node->right = NULL;//缺省情况下左右子节点设为null
int reloc,relen;
reloc = find(node->key, in, endloc);
if (reloc > 0)
node->left = creat(pre + 1, in, reloc - 1);//递归前半部分
relen = endloc - reloc;
if (relen > 0)
node->right = creat(pre + reloc + 1, in + reloc + 1, relen - 1);//递归后半部分
return node;
}
void display(DNode *p){
//递归前序输出
if (p){
cout << p->key;
display(p->left);
display(p->right);
}
}
void main(){
int pre[] = { 1, 2, 4, 7, 3, 5, 6, 8 };
int in[] = { 4, 7, 2, 1, 5, 3, 8, 6 };
DNode *p = NULL;
p = creat(pre, in, 7);
display(p);
}
总结:
这里需要说明的问题是在进行判断数组输入时,需要做一些对于非法输入的处理。这里给的代码并未包含这部分。
但是实际应用时务必要注意。否则程序必然不稳定。