title:
输入二叉树的前序和中序的遍历结果,要求重建该二叉树
1、创建一个新节点,由前序得到根节点,将其赋给新节点,再找到根节点在中序中的位置root_in,根据这一位置计算出左子树的长度len;
当数中只剩下一个节点时,就返回这一节点,此语句是递归结束语句;!!
2、根据左子树的长度计算出左子树的尾节点在位于前序的位置;
3、当左子树确定后,如果左子树的长度<整个树的长度,说明右子树不为空;
前序中:根节点之后的前len个节点为左子树,后面的属于右子树;
中序中:root_in前面的属于左子树,后面的属于右子树;
4、在3中的左右子树中分别循环1、2、3操作(递归);
注:
需要考虑的特殊情况:
输入的二叉树为空
单节点二叉树
无左子树的二叉树
无右子树的二叉树
输入二叉树的前序和中序的遍历结果,要求重建该二叉树
thought:
一般涉及到二叉树(左右子树)的操作,都会考虑用到递归方法;1、创建一个新节点,由前序得到根节点,将其赋给新节点,再找到根节点在中序中的位置root_in,根据这一位置计算出左子树的长度len;
当数中只剩下一个节点时,就返回这一节点,此语句是递归结束语句;!!
2、根据左子树的长度计算出左子树的尾节点在位于前序的位置;
3、当左子树确定后,如果左子树的长度<整个树的长度,说明右子树不为空;
前序中:根节点之后的前len个节点为左子树,后面的属于右子树;
中序中:root_in前面的属于左子树,后面的属于右子树;
4、在3中的左右子树中分别循环1、2、3操作(递归);
注:
需要考虑的特殊情况:
输入的二叉树为空
单节点二叉树
无左子树的二叉树
无右子树的二叉树
前序和中序不匹配的二叉树
#include <iostream>
#include <string>
using namespace std;
struct Btree
{
int b_value;
Btree *b_left;
Btree *b_right;
};
Btree *Rebuild(int *Preorder,int *Inorder,int len); //输入前序和中序序列,重建二叉树
Btree *Rebuild_subtree(int *start_pre,int *end_pre,int *start_in,int *end_in); //重建二叉树函数中的核心递归实现
void pre_traverse(Btree *bt);
void in_traverse(Btree *bt);
void post_traverse(Btree *bt);
Btree *Rebuild(int *Preorder,int *Inorder,int len)
{
if(NULL == Preorder || NULL == Inorder || len <= 0)
return NULL;
return Rebuild_subtree(Preorder,Preorder+len-1,Inorder,Inorder+len-1);
}
Btree *Rebuild_subtree(int *start_pre,int *end_pre,int *start_in,int *end_in)
{
Btree *root = new Btree; //创建一个头结点(前序遍历的第一个结点就是头结点)
root->b_left = NULL;
root->b_right = NULL;
root->b_value = start_pre[0];
int root_value = start_pre[0];
if(start_pre == end_pre)
{
if(start_in == end_in && *start_pre == *start_in) //判断二叉树中是否为单结点
return root;
else
throw exception("Invaild input!"); //抛出异常
}
int *root_in = start_in; //从前序中获得头结点的value
while (root_value != *root_in && start_in <= end_in) //在中序中找到值等于value的结点,此节点前面的就是左子树,后面的就是右子树
root_in++;
if(root_in == end_in && *root_in != *end_in) //当根结点指针与中序的最后结点指针指向同一个地址,但是其各自的值不相等,则抛出一个异常!(即输入的前序和中序不匹配)
throw exception("Invaild input!");
int left_length = root_in-start_in; //计算左子树的长度
int *left_end_pre = start_pre+left_length; //根据左子树的长度计算出左子树在前序中的截止位置(由头结点的下一个节点开始,到截止位置,此序列为头结点的左子树)
if(left_length > 0) //当左子树存在时,在左子树中递归重建
root->b_left = Rebuild_subtree(start_pre+1,left_end_pre,start_in,root_in-1);
if(left_length < end_pre-start_pre) //当右子树存在时,在右子树中递归重建
root->b_right = Rebuild_subtree(left_end_pre+1,end_pre,root_in+1,end_in);
return root;
}
void pre_traverse(Btree *bt)
{
if(NULL == bt)
{
cout <<"二叉树为空!" << endl;
return;
}
cout<< " " <<bt->b_value;
if(bt->b_left != NULL)
pre_traverse(bt->b_left);
if(bt->b_right != NULL)
pre_traverse(bt->b_right);
}
void in_traverse(Btree *bt)
{
if(NULL == bt)
{
cout <<"二叉树为空!" << endl;
return;
}
if(bt->b_left != NULL)
in_traverse(bt->b_left);
cout<< " " <<bt->b_value;
if(bt->b_right != NULL)
in_traverse(bt->b_right);
}
void post_traverse(Btree *bt)
{
if(NULL == bt)
{
cout <<"二叉树为空!" << endl;
return;
}
if(bt->b_left != NULL)
post_traverse(bt->b_left);
if(bt->b_right != NULL)
post_traverse(bt->b_right);
cout<< " " <<bt->b_value;
}
int main()
{
/*普通二叉树*/
//int Pre[] = {1,2,4,7,3,5,6,8};
//int In[] = {4,7,2,1,5,3,8,6};
/*无右子树的二叉树(所有节点都无右子树)*/
//int Pre[] = {1,2,3,4};
//int In[] = {4,3,2,1};
/*无左子树的二叉树(所有节点都无左子树)*/
//int Pre[] = {1,2,3,4};
//int In[] = {1,2,3,4};
/*前序和后序不匹配的二叉树*/
int Pre[] = {1,2,4,7,3,5,6,8};
int In[] = {4,7,2,1,9,3,8,6}; //抛出异常
int Len = sizeof(Pre)/sizeof(int);
Btree *bt = Rebuild(Pre,In,Len);
cout << "重建二叉树的前序遍历结果:" << endl;
pre_traverse(bt);
cout << endl;
cout << "重建二叉树的中序遍历结果:" << endl;
in_traverse(bt);
cout << endl;
cout << "重建二叉树的后序遍历结果:" << endl;
post_traverse(bt);
cout << endl;
return 0;
}