剑指Offer——由二叉树的前序中序重构
2016-07-20 11:20
363 查看
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。
假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},
则重建二叉树。
(测试用例中,"树"的输出形式类似于树的层次遍历,没有节点的用#来代替)
先序遍历:先遍历根节点,再遍历左子树,再遍历右子树,对子树采用相对规则遍历。
中序序遍历:先遍历左子树,然后遍历右子树,最后遍历根节点,对子树采用相同规则。
分析:
1:前序遍历的第一个元素,一定是这个树的根节点
2:对每棵树遍历中序遍历序列,找到与根节点元素相等节点的位置pos,根据中序遍历的特点,根节点向左的序列为左子树的中序遍历序列{4, 7, 2},根节点向右的序列为右子树的中序遍历序列{5, 3, 8, 6}.
3:根据根节点的位置可以节点的位置,可以分别求出,左右子树节点数量,这样可以在前序遍历中确认,左右子树的的前序遍历分别为{2, 4, 7},{3, 5, 6, 8}
4:对左右子树重复1,2,3步,递归求解。
5:递归返回条件,一个节点不存在子树时返回。
假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},
则重建二叉树。
(测试用例中,"树"的输出形式类似于树的层次遍历,没有节点的用#来代替)
先序遍历:先遍历根节点,再遍历左子树,再遍历右子树,对子树采用相对规则遍历。
中序序遍历:先遍历左子树,然后遍历右子树,最后遍历根节点,对子树采用相同规则。
分析:
1:前序遍历的第一个元素,一定是这个树的根节点
2:对每棵树遍历中序遍历序列,找到与根节点元素相等节点的位置pos,根据中序遍历的特点,根节点向左的序列为左子树的中序遍历序列{4, 7, 2},根节点向右的序列为右子树的中序遍历序列{5, 3, 8, 6}.
3:根据根节点的位置可以节点的位置,可以分别求出,左右子树节点数量,这样可以在前序遍历中确认,左右子树的的前序遍历分别为{2, 4, 7},{3, 5, 6, 8}
4:对左右子树重复1,2,3步,递归求解。
5:递归返回条件,一个节点不存在子树时返回。
struct BinaryTreeNode { int val; BinaryTreeNode* left; BinaryTreeNode* right; }; void TreeBuild(BinaryTreeNode *root,int *pre,int *mid,int n) { if(n<=0) return; int i; root->data=pre[0]; for(i=0;i<n;i++) { if(mid[i]==root->data) break;//在中序遍历中寻找左子树的长度为i. } if(i>0)//左子树不为空 { root->left=new BinaryTreeNode(); TreeBuild(root->left,pre+1,mid,i); } if(i<n-1)//右子树不为空 { root->right=new BinaryTreeNode(); TreeBuild(root->right,pre+i+1,mid+i+1,n-i-1); } } //剑指Offer给的解题思路 BinaryTreeNode *TreeBuildCore(int *pre1,int *pre2,int *mid1,int *mid2)//pre1与pre2分别代表二叉树前序遍历的开始和结束指针 { int rootval=pre1[0];//头结点的值 BinaryTreeNode *root=new BinaryTreeNode();//新建根结点 root->val=rootval; root->left=root->right=NULL; if(pre1==pre2) { if(mid1==mid2&&*pre1==*mid1) return root;//只有一个结点 else throw std::exception("Invalid input"); } int *rootmid=mid1; //在中序遍历中查找根节点位置 while(rootmid<=mid2&&rootmid!=rootval) rootmid++; if(rootmid==mid2&&*rootmid!=rootval)//在中序遍历中未找到头结点,报错 throw std::exception("Invalid input"); int leftlen=rootmid-mid1;//左子树的长度 int *leftpre2=pre1+leftlen; if(leftlen>0) { //左子树不为空 root->left=TreeBuildCore(pre1+1,leftpre2,mid1,rootmid-1); } if(leftlen<pre2-pre1) { //右子树不为空 root->right=TreeBuildCore(leftpre2+1,pre2,rootmid+1,mid2); } return root; } BinaryTreeNode *TreeBulid(int *pre,int *mid,int length) { if(pre==NULL||mid==NULL||length<=0) return NULL; return TreeBuildCore(pre,pre+length-1,mid,mid+lenght-1); }
相关文章推荐
- 设置input上传类型
- 【phantomjs】使用phantomjs生成highChart的图片(待完善)
- web前端开发技术文档书写规范
- JQuery根据name属性查找
- jQuery中ready与load事件的区别
- 从零开始的 React 组件开发之路 (一):表格篇
- 推荐一些国内的Jquery CDN免费服务
- javascript—闭包
- Cannot create __weak reference in file using manual refs Xcode 7.3
- CSS中 -gradient && background
- RadioButton和CheckBox自定义按钮图片的样式
- JQuery为元素添加样式的实现方法
- Array.map()
- Jsp页面动态显示当前时间
- CSS 清除浮动代码
- css图片图片居中显示
- JavaScript的预编译
- js正则表达式
- 用fastjson解析json数据顺序问题,用gson完美解决
- 神器推荐:应用之星,零代码就能制作炫酷的H5页面