题目

这道题和后面的两道题,题目1201和题目1009,主要内容是对递归的实现,在逻辑上,递归是容易理解的,这种实现方式和我们思考的方式是相吻合的。但是在转换为计算机语言时,要明确告知计算机应该从哪里开始启用新一层的递归,带着什么参数去启用新一层的递归,最终返回什么值。所谓的一层递归,界限在哪里,递归函数体中的形参和逻辑流程中的实参要区分清楚。这些问题都是在实现递归时需要好好琢磨的。

思路

  • 手工解决重构二叉树时,先在“先序序列”中确定根,再在“中序序列”中确定左右子树。
  • 转换为代码,用递归来实现上述过程。用结构体存放树。 用结构体来定义节点,用静态数组存放树。
    • 之所以用静态数组来存放树,是因为这样简化了内存操作。标准做法是动态申请、动态释放,但是这样做需要更小心。
    • 按照初始状态实现第一个递归实例
    • “递归总是以一个函数的形态出现”,实现第一个递归实例时,并没有意识到这一点,于是先在main中写出了递归的函数体,而后才抽出来写成新的递归函数体build()
    • 按照思路中直观地实现,给函数传递的参数都是“字符串”,包括先序序列、中序序列、左子序列、右子序列。
    • 然后就不知道怎么进行递归了:怎样自己(build)调用自己(build)呢?被困在这一步。

实现递归

  • 递归函数build的参数必须十分讲究:这些参数必须便于描述清楚“某次调用,将操作哪些数据。”

    • 反思:上面被困住的原因是,build的参数选择不当,每次都要传入字符串,而且会拆分字符串,第二层递归build调用了子串A,那么余下的子串B怎么处理?暂存?
    • 正确做法是,原来的数据本身在内存中一个地方不能动(不可传入递归做修改),能很方便地移动的是下标、指针。
  • 递归的参数一般都是“下标”或者“指针”这类索引性质的变量,不能是数据本身!
    • 反思:递归函数的参数是变量,上面实现第一个递归实例时的想法并没有这么明确
    • 只是想着先把第一次递归的操作实现出来。
    • 下一步的思路应该是,将这次实现中用到的递归函数的参数都“抽象出来、提取出来”——形成形式参数
    • 递归函数体中的形式参数是每一层递归实例中要用来接收实参的变量,如何从具体实现中选取合适的提取对象(形参的候选者)是关键。
  • 当递归函数的形式参数是下标或指针时,调用新一层递归,主要是如何对这些下标和指针进行运算,来传入正确的实参
    • 先具体:从第一次递归实例进入第二次递归实例,需要如何移动下标,加减下标,可以用一些具体数字计算
    • 后抽象:将上面用的数字,逐个抽象为公式
    • 类似于数学归纳。

调试中的小问题

  • strlen()在标准C++中的头文件是cstring,在Virsual Studio中包含string也可使用,但在标准C++中却编译出错。
  • if判断中,是否添加一个等号,都至关重要,可能就是一个等号,逻辑出错,而且不是语法错误,要选择全面的测试数据、调试很久才能发现。

完整代码

#include <stdio.h>
#include <string>
//二叉树结点定义
typedef struct BTNode {char data;BTNode * lchild;BTNode * rchild;
} BTNode;
//二叉树定义
/*若用静态数组就不需要这个
typedef struct BTree {BTNode * root;int nodeNum;
} BTree;
*/
BTNode tree[50];
int loc; //用于保存静态数组中已分配出去的元素的个数
char pre[30];
char in[30];
//char ltemp[30];这是旧思路中使用的
//char rtemp[30];
//该函数根据前序和中序将序列分解
/*递归写的不好,传入的参数不对,返回值也不对*传入子串,修改子串,是直观的,与思路相吻合的,但是不利于递归*下面用下标来作为参数传入该递归函数,以下标来表示子串,便于递归操作
void splice(char & preOrder, char & inOder, char & leftTemp, char & rightTemp) {int i;for (i = 0; inOder[i] != preOrder[0]; i++);for (int j = 0; j < i; j++) {leftTemp[j] = preOrder[j];}i++;for (int j = 0; preOrder[i] != 0; i++, j++) {rightTemp[j] = preOrder[i];}
}
*/
//如果是动态申请内存就是为新节点申请内存,这里只需要loc++就表示占用预分配的数组中一个位置,产生一个新节点
BTNode * creat() {tree[loc].lchild = tree[loc].rchild = NULL;return &tree[loc++];
}
//构建二叉树
BTNode * build(int s1, int e1, int s2, int e2) {BTNode * ret = creat(); //最终要返回的指针ret->data = pre[s1];int rootIdx;//【错误1】for (int i = s2; i < e2; i++) { 若子树中仅有一个节点,没有=直接不进入循环,造成错误for (int i = s2; i <= e2; i++){ //找到根节点在中序序列中的下标if (pre[s1] == in[i]) {rootIdx = i;    break;}}if (s2 != rootIdx) {ret->lchild = build(s1 + 1, s1 + (rootIdx - s2), s2, rootIdx - 1); //【重要】递归的核心在此处的参数如何计算}if (rootIdx != e2) {ret->rchild = build(s1 + (rootIdx - s2) + 1, e1, rootIdx + 1, e2);}return ret;
}
//后序遍历
void postOrder(BTNode *root) {if (root->lchild)postOrder(root->lchild);if (root->rchild)postOrder(root->rchild);printf("%c", root->data);
}
int main()
{while (scanf("%s%s", pre, in) != EOF) {int start1 = 0, start2 = 0;int end1 = strlen(pre) - 1, end2 = strlen(in) - 1;loc = 0;BTNode * BTRoot = build(start1, end1, start2, end2); //一次调用就构建了二叉树postOrder(BTRoot);printf("\n");}return 0;
}

转载于:https://www.cnblogs.com/tambura/p/5227597.html

【九度OJ】题目1078-二叉树遍历相关推荐

  1. 九度oj 题目1078:二叉树遍历

    题目1078:二叉树遍历 时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:5326 解决:3174 题目描述: 二叉树的前序.中序.后序遍历的定义: 前序遍历:对任一子树,先访问跟,然后遍历 ...

  2. 九度OJ 题目1179:阶乘

    /********************************* * 日期:2013-2-8 * 作者:SJF0115 * 题号: 九度OJ 题目1179:阶乘 * 来源:http://ac.jo ...

  3. 九度OJ 题目1069:查找学生信息 随笔

    ** 九度OJ 题目1069:查找学生信息 ** 题目描述如下: 输入N个学生的信息,然后进行查询. 输入 输入的第一行为N,即学生的个数(N<=1000) 接下来的N行包括N个学生的信息,信息 ...

  4. 九度OJ 题目1203:IP地址

    /********************************* * 日期:2013-2-8 * 作者:SJF0115 * 题号: 九度OJ 题目1203:IP地址 * 来源:http://ac. ...

  5. 九度oj题目1385:重建二叉树

    题目1385:重建二叉树 时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:4419 解决:1311 题目描述: 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树.假设输入的前序遍历和 ...

  6. 九度oj 题目1354:和为S的连续正数序列

    题目描述: 小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100.但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为100(至少包括两个数).没多久, ...

  7. 九度OJ—题目1032:ZOJ

    题目描写叙述: 读入一个字符串.字符串中包括ZOJ三个字符,个数不一定相等,按ZOJ的顺序输出.当某个字符用完时,剩下的仍然依照ZOJ的顺序输出. 输入: 题目包括多组用例,每组用例占一行,包括ZOJ ...

  8. 九度oj 题目1411:转圈

    题目描述: 在一个有向图有n个顶点(编号从1到n),给一个起点s,问从起点出发,至少经过一条边,回到起点的最短距离. 输入: 输入包括多组,每组输入第一行包括三个整数n,m,s(1<=n< ...

  9. 【WA】九度OJ题目1435:迷瘴

    题目描述: 通过悬崖的yifenfei,又面临着幽谷的考验-- 幽谷周围瘴气弥漫,静的可怕,隐约可见地上堆满了骷髅.由于此处长年不见天日,导致空气中布满了毒素,一旦吸入体内,便会全身溃烂而死. 幸好y ...

  10. 九度oj 题目1376:最近零子序列

    题目描述: 给定一个整数序列,你会求最大子串和吗?几乎所有的数据结构与算法都会描述求最大子串和的算法.今天让大家来算算最近0子串和,即整数序列中最接近0的连续子串和.例如,整数序列6, -4, 5, ...

最新文章

  1. 让我们来开发一种更类似人脑的神经网络吧(三)
  2. 简单记录js中的this关键字
  3. 随笔(二)-- PyCharm如何更改背景图片
  4. LeetCode Algorithm 3. 无重复字符的最长子串
  5. linux c 内存elf,gcc加入linux ELF有什么功能?
  6. 魅族16s Pro邀请函发布:对称式全面屏+骁龙855Plus
  7. Visual Studio Code 10 月 Python 扩展更新
  8. 利用计算机打字教学设计,《争当打字小能手》教学设计方案
  9. java程序员目标_Java程序员的目标,你都达到了多少条?
  10. 黑客利用域前置技术攻击缅甸政府并隐藏恶意活动
  11. shiro-cas------整合springboot客户端
  12. 浏览器中加载CNN进行手写数字识别,并部署到Gitee Page
  13. dw新建html快捷键,DW软件新建一个html网页
  14. win8.1打开网络上的计算机没有权限,Win8无网络访问权限_Win8无internet访问权限怎么解决-192路由网...
  15. 专升本培训机构如何用自媒体做品牌推广
  16. word2016使用Latex编辑公式
  17. 嵌入式Linux C笔试题积累
  18. 多表联合查询(join、union等)
  19. 【Python项目】圣诞节快到了,Python基于海龟(turtle)实现的圣诞树效果,是好几个哟 | 附源码
  20. 龙泉驿区!成都经开区支持扩大汽车消费政策申报条件时间及认定奖励补助

热门文章

  1. [学习笔记]数字电路技术
  2. CTFshow 命令执行 web73
  3. 设置VMWARE通过桥接方式使用主机无线网卡上网
  4. delphi项目文件说明
  5. int (*a)[10] 和 int *a[10] 的区别
  6. C++ Vector用法深入剖析
  7. Maven实战读书笔记(六):Maven灵活构建
  8. 百度定位sdk使用说明
  9. 20169205实验一 Java开发环境的熟悉(Linux+IDEA)
  10. 【书评】RHCSA/RHCE Red Hat Linux 认证学习指南(第6版)EX200 EX300