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 重建二叉树相关推荐

  1. 剑指offer:面试题07. 重建二叉树

    题目: 重建二叉树 输入某二叉树的前序遍历和中序遍历的结果,请重建该二叉树.假设输入的前序遍历和中序遍历的结果中都不含重复的数字. 例如,给出 前序遍历 preorder = [3,9,20,15,7 ...

  2. 根据二叉树的前序遍历和中序遍历重建二叉树

    题目描述 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树.假设输入的前序遍历和中序遍历的结果中都不含重复的数字.例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7, ...

  3. 剑指offer_第4题_重建二叉树

    题目描述 输入某二叉树的前序遍历和中序遍历的结果 请重建出该二叉树 假设输入的前序遍历和中序遍历的结果中都不含重复的数字.例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7, ...

  4. python根据二叉树的前序遍历和中序遍结果历重建二叉树

    python根据二叉树的前序遍历和中序遍结果历重建二叉树 前序遍历 对于当前节点,先输出该节点,然后输出他的左孩子,最后输出他的右孩子.以上图为例,递归的过程如下: (1):输出 1,接着左孩子: ( ...

  5. 《编程之美》读书笔记19: 3.9 重建二叉树

    <编程之美>读书笔记19: 3.9 重建二叉树 对根节点a以及先序遍历次序P和中序遍历次序I,查找a在I中的位置,将I分为两部分,左边部分的元素都在a的左子树上,右边的元素都在a的右子树上 ...

  6. 剑指Offer系列 重建二叉树

    题目:输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树. 假设输入的前序遍历和中序遍历的结果中都不含重复的数字. 例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7, ...

  7. 剑指offer——面试题7:重建二叉树

    1 // 面试题7:重建二叉树 2 // 题目:输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树.假设输 3 // 入的前序遍历和中序遍历的结果中都不含重复的数字.例如输入前序遍历序列{1, ...

  8. 【剑指Offer】面试招聘题目2:重建二叉树

    题目链接:http://ac.jobdu.com/problem.php?cid=1039&pid=1 题目描述: 题目描述: 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树.假设输 ...

  9. JAVA实现重建二叉树(《剑指offer》)

    最近在刷<剑指offer>里的编程题,但是网上关于<剑指offer>的解答多半是C或者C++的,而且官方(作者)也是在用C++进行讲解,这里自己用java写了一些题目的解答代码 ...

最新文章

  1. 十大双跨平台整体发展情况盘点
  2. java服务端无法发送给客户端,无法从客户端向服务器发送消息
  3. Java实现蛇形矩阵
  4. excel : 如何快速跳到某一行
  5. java注解_Java注解
  6. Python Sklearn.metrics 简介及应用示例(机器学习各种评价指标)
  7. Java并发编程学习笔记(一)线程安全性 1
  8. java+mysql实现图书管理系统
  9. JavaWeb项目结构
  10. 使用selenium + pytest + allure做WBE UI自动化
  11. 使用hightopo完成基本图元旋转和闪烁
  12. soul网关-4-sign插件签名认证
  13. QR码国家标准(图片和表格后续会更新)
  14. sublime软件中如何给很多行数据加逗号及双引号并转换成一行?
  15. 机器学习与统计建模 —— 差异和联系
  16. IconResource:安卓、IOS、网页等开发图标素材源
  17. 华为实验——两核心两接入一路由配置
  18. 第五天 游戏策划学习
  19. 如何从SAP Business One的HANA数据库中提取数据用于数据分析?
  20. ORACLE去重排序

热门文章

  1. Java并发机制深究1-synchronized和volatile
  2. J2EE项目工具集(转)
  3. SQL 模糊查询技术
  4. poj 2063 Investment(01背包变形)
  5. 【跃迁之路】【535天】程序员高效学习方法论探索系列(实验阶段292-2018.07.25)...
  6. ArrayList初步
  7. 预处理器预处理变量头文件保护条件编译
  8. 只用jsp实现同样的Servlet功能
  9. C结构体工具DirectStruct(综合示例二)
  10. 邮件发送打印机更改打印机连接的通知