根据二叉树的前序遍历和中序遍历,重构出二叉树
来源:互联网 发布:视频音乐 制作软件 编辑:程序博客网 时间:2024/05/22 11:58
题目:这道题目是一道面试题,先序遍历和中序遍历以数组的形式给出,要求我们根据这两个条件重构出二叉树。
下图是一棵二叉树
// 6// / \// 5 7 // / \ \// 2 4 8
先序遍历:6,5,2,4,7,8
中序遍历:2,5,4,6,7,8
思路:二叉树先序遍历的定义:1,先输出根结点2,再输出左子树3,再输出右子树,因此先序遍历时,根结点总会出现在数组开头,中序遍历时,根结点可以将二叉树分为左右子树。
因此,重构二叉树的步骤可以用自顶向下的方法:
1,先在先序序列中找到根结点,
2,在中序序列中找到根结点位置,(可以将二叉树分为左子树和右子树)
3.用同样的办法构造左子树
4.用同样的办法构造右子树。
例如:
1.找到根结点6,因此左子树是2,5,4和右子树是7,8
2.找到左边根结点5,可将子二叉树分为2和4,因此左边确定。
3,找到右边根结点7,因此可确定右子树8。
根据四步走可以写出如出代码:
node* Build_Tree(int* prec,int* inorder,int len){//步骤1:新建根结点node* root=new node(prec[0]);//步骤2:在中序遍历中找到根结点索引,分割左右子树int SubTreeLen=0;while(SubTreeLen < len && inorder[SubTreeLen] != prec[0])++SubTreeLen;if(SubTreeLen > 0){//步骤2:重建左子树,并且将根结点root的left指向左子树root->left=Build_Tree(prec+1,inorder,SubTreeLen);}if(len-SubTreeLen-1 > 0){//步骤2:重建右子树,并且将根结点root的left指向右子树root->right=Build_Tree(prec+1+SubTreeLen,inorder+1+SubTreeLen,len-SubTreeLen-1);}return root;}
接下来的步骤就是进行程序测试,利用边界值等去测试程序的健壮性。
可以利用下面的二叉树去测试:
// 普通二叉树// 1// / \// 2 3 // / / \// 4 5 6// \ /// 7 8int preorder[length] = {1, 2, 4, 7, 3, 5, 6, 8};int inorder[length] = {4, 7, 2, 1, 5, 3, 8, 6};// 所有结点都没有右子结点// 1// / // 2 // / // 3 // /// 4// /// 5int preorder[length] = {1, 2, 3, 4, 5};int inorder[length] = {5, 4, 3, 2, 1};// 所有结点都没有左子结点// 1// \ // 2 // \ // 3 // \// 4// \// 5int preorder[length] = {1, 2, 3, 4, 5};int inorder[length] = {1, 2, 3, 4, 5};// 树中只有一个结点 int preorder[length] = {1}; int inorder[length] = {1};// 完全二叉树// 1// / \// 2 3 // / \ / \// 4 5 6 7 int preorder[length] = {1, 2, 4, 5, 3, 6, 7}; int inorder[length] = {4, 2, 5, 1, 6, 3, 7};// 输入空指针// 输入的两个序列不匹配 int preorder[length] = {1, 2, 4, 5, 3, 6, 7}; int inorder[length] = {4, 2, 8, 1, 6, 3, 7};
上述测试例子引自于:《剑指Offer——名企面试官精讲典型编程题》
经过测试,当输入空指针和两个序列不匹配时,原始的程序无办法处理,可以针对性处理如下:
#include<iostream>#include <exception>using std::cout;using std::endl;struct node{int value;node* left;node* right;node(int v):value(v),left(NULL),right(NULL){}};node* Build_Tree(int* prec,int* inorder,int len){if(!prec || !inorder || len <=0 ){cout<<"Empty Input!"<<endl;exit(1);//暴力关机}//步骤1:新建根结点node* root=new node(prec[0]);//步骤2:在中序遍历中找到根结点索引,分割左右子树int SubTreeLen=0;while(SubTreeLen < len && inorder[SubTreeLen] != prec[0])++SubTreeLen;if(SubTreeLen == len)//越界了,说明两个数组无法构造出二叉树{cout<<"Wrong Input!"<<endl;exit(1);//暴力关机}if(SubTreeLen > 0){//步骤2:重建左子树,并且将根结点root的left指向左子树root->left=Build_Tree(prec+1,inorder,SubTreeLen);}if(len-SubTreeLen-1 > 0){//步骤2:重建右子树,并且将根结点root的left指向右子树root->right=Build_Tree(prec+1+SubTreeLen,inorder+1+SubTreeLen,len-SubTreeLen-1);}return root;}void prec_tree_walk(node* z){if(!z)return ;cout<<z->value<<' ';prec_tree_walk(z->left);prec_tree_walk(z->right);}void inorder_tree_walk(node* z){if(!z)return ;inorder_tree_walk(z->left);cout<<z->value<<' ';inorder_tree_walk(z->right);}int main(){int prec[] = {1, 2, 4, 7, 3, 5, 6, 8};int Inorder[] = {4, 7, 2, 1, 5, 3, 8, 6};int len=sizeof(prec)/sizeof(prec[0]);node* root=Build_Tree(prec,Inorder,len);prec_tree_walk(root);cout<<endl;inorder_tree_walk(root);return 0;}中途发现的编译错误记录如下:点击打开链接
- 根据二叉树的前序遍历和中序遍历,重构出二叉树
- 【二叉树】根据二叉树的中序遍历和前序遍历,还原二叉树
- 根据二叉树的前序遍历和中序遍历的结果,重建二叉树
- 根据二叉树的前序遍历和中序遍历重建二叉树
- 根据二叉树的前序遍历和中序遍历,重构二叉树
- 根据二叉树的前序遍历和中序遍历构造二叉树
- 根据前序和中序遍历构造二叉树
- 根据前序和中序遍历构造二叉树
- 根据中序和前序遍历重建二叉树
- 根据中序和前序遍历构建二叉树
- 根据前序和中序遍历重建二叉树
- 根据前序遍历,中序遍历构建二叉树
- 根据前序遍历、中序遍历重建二叉树
- 根据前序遍历中序遍历求二叉树
- 根据前序遍历和中序遍历重建二叉树的Java实现
- offer面试题---根据前序遍历和中序遍历的顺序输出二叉树
- 根据前序遍历和后续遍历建立二叉树
- 根据二叉树的前序遍历和中序遍历构建二叉树的c语言完整代码
- 如何找回格式化后的数据
- 通过SQLServer的xp_cmdshell在服务器之间传送文件
- 计算机网络基本概念趣解(续)
- HDU 1756 Cupid's Arrow(判断点是否在多边形内部)
- SCU 1187: Closest Common Ancestors
- 根据二叉树的前序遍历和中序遍历,重构出二叉树
- sql数据库对重复记录的处理
- 求助ET服装打版软件
- hdu 计算直线的交点
- 测试Kettle在增量更新的时候是否支持级联——不支持(基于mysql)
- 常用RGB表
- 关于SubSonic3.0生成的表名自动加复数(s)的“用户代码未处理SqlException,对象名'xxxs'无效”异常处理
- 在linux上增加swap交换空间
- POJ3318--Matrix Multiplication