Programe_Of_Beauty :3.9 重建二叉树
1.问题定义
对于二叉树的3中遍历方法,相信大家耳熟能详。那么如果我们知道了其中的两种遍历结果,能不能把一棵二叉树重新建立起来?给定一棵二叉树,假设每个节点都用唯一的字符来表示,没有重复。结构如下:
struct _Node {_Node* Lchild;_Node* Rchild;char data; };
假设已有了前序遍历和中序遍历的结果,希望通过一个算法来重建这棵树。
前序遍历:a, b, d, c, e, f 显然a是根节点
中序遍历:d, b, a, e, c, f a前面的d, b是a的左子树中的节点,a后面的e, c, f是a右子树中的节点
重建后的图如下:
2.分析与解法
不难发现a是前序遍历中的第一个节点,把中序遍历分成前后两个部分,分别是a的左右子树中的节点,长度分别为2,3,前序遍历中的第二个节点b又把d, b分成了前后两部分(后一部分没有节点),分别是b的左右子树中的节点,长度分别为1,0……这样递归下去,能找出每一个节点的左右子树中的节点,当节点没有左右子树的时候即为叶节点,当一个节点它的左右子树长度为1时,此节点的左右子树就一个节点,为0时,表示此节点没有左子树或右子树。编程之美上的算法如下:
#include <iostream>using namespace std; #define TREELEN 6 struct _Node {_Node* Lchild;_Node* Rchild;char data; }; void ReBulid(char* pPreOrder,//当前节点的前序遍历结果 char* pInOrder, //当前节点的中序遍历结果int nTreeLen, //当前节点为根的树长度_Node**pRoot) //当前根节点 {if (pPreOrder == NULL || pInOrder == NULL)//边界检查{return;}_Node* pTemp = new _Node;pTemp->data = *pPreOrder;pTemp->Lchild = NULL;pTemp->Rchild = NULL;if (*pRoot == NULL)//如果当前根节点为空,把前序遍历的第一个节点赋给它{*pRoot = pTemp;}if (nTreeLen == 1)//如果当前树长度为1,表明此节点是最后一个节点{return;}//寻找子树长度char* pOrgInOrder = pInOrder;char* pLeftEnd = pInOrder;int nTempLen = 0;//找到左子树的结尾while(*pPreOrder != *pLeftEnd){if (pPreOrder == NULL || pLeftEnd == NULL){return;}nTempLen++;if (nTempLen > nTreeLen){break;}pLeftEnd++;}//寻找左子树长度int nLeftLen = 0;nLeftLen = (int)(pLeftEnd - pOrgInOrder);//寻找右子树长度int nRightLen = 0;nRightLen = nTreeLen - nLeftLen - 1;//重建左子树if (nLeftLen > 0){ReBulid(pPreOrder + 1, pInOrder, nLeftLen, &((*pRoot)->Lchild));}//重建右子树if (nRightLen > 0){ReBulid(pPreOrder + nLeftLen + 1, pInOrder + nLeftLen + 1, nRightLen, &((*pRoot)->Rchild));} }; void main() {char PerO[6] = {'a', 'b', 'd', 'c', 'e', 'f'};char InO[6] = {'d', 'b', 'a', 'e', 'c', 'f'};_Node * pRoot = NULL;ReBulid(PerO, InO, TREELEN, &pRoot); }
这里可能引起内存泄露。_Node * pRoot = NULL;并没有释放空间,详见:http://blog.csdn.net/flyinghearts/archive/2010/05/31/5638123.aspx
另这里给几个内存思考问题(有点肤浅,见笑):
void GetMemory(char *p) {p = (char *)malloc(100); } void Test(void) {char *str = NULL;GetMemory(str);strcpy(str, "hello world");printf(str); } 请问运行Test 函数会有什么样的结果? 答:程序崩溃。 因为 GetMemory 并不能传递动态内存,Test 函数中的 str 一直都是 NULL。 strcpy(str, "hello world");将使程序崩溃
char *GetMemory(void) {char p[] = "hello world";return p; } void Test(void) {char *str = NULL;str = GetMemory();printf(str); } 请问运行Test 函数会有什么样的结果? 答:可能是乱码。 因为 GetMemory 返回的是指向“栈内存”的指针,该指针的地址不是 NULL,但其原 现的内容已经被清除,新内容不可知。
void GetMemory2(char **p, int num) {*p = (char *)malloc(num); } void Test(void) {char *str = NULL;GetMemory(&str, 100);strcpy(str, "hello");printf(str); } 请问运行Test 函数会有什么样的结果? 答: (1)能够输出hello (2)内存泄漏
void Test(void) {char *str = (char *) malloc(100);strcpy(str, “hello”);free(str);if(str != NULL){strcpy(str, “world”);printf(str);} } 请问运行Test 函数会有什么样的结果? 答:篡改动态内存区的内容,后果难以预 料,非常危险。因为 free(str);之后,str 成为野指针,if(str != NULL)语句不起作用。
//关于重建二叉树的方法,还有很多。我觉得有一种方法也可行:假如前序遍历的为a,b,c,那么中序遍历的结果只有5种:c,b,a | a,b,c | b,c,a | c,b,a | b,a,c。
当然前提是前序遍历的头两个节点,即a,b不能有共同的父亲。用a,b,c找出中序遍历中a,b,c分别的位置,就对应出a,b,c的树型结构。
还有一点,a是根节点,这没问题,一定要用a先找完a的左子树,然后再用a找完a的右子树,如前序:a,b,d,e,x,g,c,k,h,z , 中序为:d,b,x,g,e, (a) ,k,c,h,z
要这样操作:先a,b,d,e,x,g ->(a,b,d) ->(b,d,e)->(d,e,x)->(e,x,g)->(x,g)。然后a,c,k,h,z->(a,c,k)->(,c,k,h)->(k,h,z)->(h,z)。
*还要注意:(a,b,d)中前两个节点a,b不能有共同的父亲,否则这步操作不作!那么最后只有两个节点怎么办呢?
如:(x,g),如果在中序遍历中g在a的前面则说明g是a的右孩子,即中序中x,g反序了。否则g为a的左孩子。
转载于:https://www.cnblogs.com/cluster/archive/2011/05/29/2062127.html
Programe_Of_Beauty :3.9 重建二叉树相关推荐
- 剑指offer:面试题07. 重建二叉树
题目: 重建二叉树 输入某二叉树的前序遍历和中序遍历的结果,请重建该二叉树.假设输入的前序遍历和中序遍历的结果中都不含重复的数字. 例如,给出 前序遍历 preorder = [3,9,20,15,7 ...
- 根据二叉树的前序遍历和中序遍历重建二叉树
题目描述 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树.假设输入的前序遍历和中序遍历的结果中都不含重复的数字.例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7, ...
- 剑指offer_第4题_重建二叉树
题目描述 输入某二叉树的前序遍历和中序遍历的结果 请重建出该二叉树 假设输入的前序遍历和中序遍历的结果中都不含重复的数字.例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7, ...
- python根据二叉树的前序遍历和中序遍结果历重建二叉树
python根据二叉树的前序遍历和中序遍结果历重建二叉树 前序遍历 对于当前节点,先输出该节点,然后输出他的左孩子,最后输出他的右孩子.以上图为例,递归的过程如下: (1):输出 1,接着左孩子: ( ...
- 《编程之美》读书笔记19: 3.9 重建二叉树
<编程之美>读书笔记19: 3.9 重建二叉树 对根节点a以及先序遍历次序P和中序遍历次序I,查找a在I中的位置,将I分为两部分,左边部分的元素都在a的左子树上,右边的元素都在a的右子树上 ...
- 剑指Offer系列 重建二叉树
题目:输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树. 假设输入的前序遍历和中序遍历的结果中都不含重复的数字. 例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7, ...
- 剑指offer——面试题7:重建二叉树
1 // 面试题7:重建二叉树 2 // 题目:输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树.假设输 3 // 入的前序遍历和中序遍历的结果中都不含重复的数字.例如输入前序遍历序列{1, ...
- 【剑指Offer】面试招聘题目2:重建二叉树
题目链接:http://ac.jobdu.com/problem.php?cid=1039&pid=1 题目描述: 题目描述: 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树.假设输 ...
- JAVA实现重建二叉树(《剑指offer》)
最近在刷<剑指offer>里的编程题,但是网上关于<剑指offer>的解答多半是C或者C++的,而且官方(作者)也是在用C++进行讲解,这里自己用java写了一些题目的解答代码 ...
最新文章
- 十大双跨平台整体发展情况盘点
- java服务端无法发送给客户端,无法从客户端向服务器发送消息
- Java实现蛇形矩阵
- excel : 如何快速跳到某一行
- java注解_Java注解
- Python Sklearn.metrics 简介及应用示例(机器学习各种评价指标)
- Java并发编程学习笔记(一)线程安全性 1
- java+mysql实现图书管理系统
- JavaWeb项目结构
- 使用selenium + pytest + allure做WBE UI自动化
- 使用hightopo完成基本图元旋转和闪烁
- soul网关-4-sign插件签名认证
- QR码国家标准(图片和表格后续会更新)
- sublime软件中如何给很多行数据加逗号及双引号并转换成一行?
- 机器学习与统计建模 —— 差异和联系
- IconResource:安卓、IOS、网页等开发图标素材源
- 华为实验——两核心两接入一路由配置
- 第五天 游戏策划学习
- 如何从SAP Business One的HANA数据库中提取数据用于数据分析?
- ORACLE去重排序