编程之美 3.9 重建二叉树 扩展问题
来源:互联网 发布:linux怎么改变用户目录 编辑:程序博客网 时间:2024/05/01 11:26
编程之美 3.9 重建二叉树
给定函数的定义如下:
void Rebuild(char* pPreOrder, char* pInOrder, int nTreeLen, NODE** pRoot);
参数
前序遍历结果:a b d c e f
中序遍历结果:d b a e c f
递归结束条件是长度小于1,此时令*pRoot=NULL即可。
递归主体中,在中序遍历结果中找前序结果的第一个字符,找到后记录其下标为index,
如果找不到说明前序遍历和中序遍历有问题,说明错误信息,然后直接返回。找到index后,新建一个节点,让*pRoot指向它,其数值为前序的第一个字符,
然后递归求*pRoot的左孩子和右孩子。
递归左孩子:Rebuild( pPreOrder+1,pInOrder, index, &((*pRoot)->pLeft) )
递归右孩子:Rebuild( pPreOrder+index+1, pInOrder+index+1, nTreeLen-index-1, &((*pRoot)->pRight) )
搜索所有可能的情况,并调用扩展问题2的解决方案,判断此情况是否合理(剪枝操作),
如果合法,则构造解
递归算法实现,分别遍历左右子树,递归中迭代查找左右子树的长度,类似于书中的方法。
http://blog.csdn.net/luyafei_89430/article/details/12967411
对于满二叉树,利用子树节点的排列顺序能区分开左右子树节点集合,构建是没有问题的。但一旦有单个叶子的节点存在,则无法确定叶子是左儿子还是右儿子。因为无论是前序还是后序序列,都无法体现单个儿子情况下,儿子的位置。前序会将左右子树的点置于节点之后,后序则是将左右子树的点置于节点之前。
举个简单的反例:
给出如下的前序序列和后序序列: preorder: A, B; postorder: B, A能构建的二叉树有两种可能,1.A 是根节点,B 是 A 左儿子; 2.A 是根节点, B 是 A 的右儿子。无法得到一个唯一的结果。
总结
中序遍历配合另外任何一个遍历,能重建二叉树。其他的任意两个序列的组合都不能唯一的确定重建的二叉树。
附:已知后序和中序:
题目描述:
给定一棵二叉树,假定每个节点都用唯一的字符表示,具体结构如下:struct NODE { NODE* pLeft; NODE* pRight; char chValue;};假设已经有了前序遍历和中序遍历结果,希望通过一个算法重建这棵树。
给定函数的定义如下:
void Rebuild(char* pPreOrder, char* pInOrder, int nTreeLen, NODE** pRoot);
参数
pPreOrder:前序遍历结果的字符串数组。例如
pInOrder: 中序遍历结果的字符串数组。
nTreeLen: 树的长度。
pRoot: 根据前序和中序遍历结果重新构建树的根节点。
前序遍历结果:a b d c e f
中序遍历结果:d b a e c f
分析与解法
递归实现递归结束条件是长度小于1,此时令*pRoot=NULL即可。
递归主体中,在中序遍历结果中找前序结果的第一个字符,找到后记录其下标为index,
如果找不到说明前序遍历和中序遍历有问题,说明错误信息,然后直接返回。找到index后,新建一个节点,让*pRoot指向它,其数值为前序的第一个字符,
然后递归求*pRoot的左孩子和右孩子。
递归左孩子:Rebuild( pPreOrder+1,pInOrder, index, &((*pRoot)->pLeft) )
递归右孩子:Rebuild( pPreOrder+index+1, pInOrder+index+1, nTreeLen-index-1, &((*pRoot)->pRight) )
#include <iostream>#include<stdio.h>using namespace std;struct NODE { NODE* pLeft; NODE* pRight; char chValue;};void Rebuild(char* pPreOrder, char* pInOrder, int nTreeLen, NODE** pRoot) { if(nTreeLen<= 0) { *pRoot = NULL; return; } else { int index = 0; while(index<nTreeLen&&pPreOrder[0]!=pInOrder[index]) index++; if(index>=nTreeLen) { cout << "前序和中序字符串不匹配,有问题" << endl; cout << "在中序字符串中,找不到:" << pPreOrder[0] << endl; return; } else { *pRoot = new NODE; (*pRoot)->chValue = pPreOrder[0]; Rebuild(pPreOrder+1, pInOrder, index, &((*pRoot)->pLeft)); Rebuild(pPreOrder+index+1, pInOrder+index+1, nTreeLen-index-1, &((*pRoot)->pRight) ); } } }void BaOrder(NODE *tree) { if(tree!=NULL) { BaOrder(tree->pLeft); BaOrder(tree->pRight);printf("%c ",tree->chValue); } }int main() { char* pPreOrder = "abdcef"; char* pInOrder = "dbaecf"; NODE* pRoot; Rebuild(pPreOrder, pInOrder, strlen(pPreOrder), &pRoot); BaOrder(pRoot); //后序 d b e f c a return 0;}
扩展问题1:
如果前序和中序遍历的字母有重复的,那么怎么构造所有可能的解呢?搜索所有可能的情况,并调用扩展问题2的解决方案,判断此情况是否合理(剪枝操作),
如果合法,则构造解
扩展问题2:
如何判断给定的前序遍历和中序遍历的结果是合理的?递归算法实现,分别遍历左右子树,递归中迭代查找左右子树的长度,类似于书中的方法。
http://blog.csdn.net/luyafei_89430/article/details/12967411
扩展问题3:
如果知道前序和后序的结果,能重构二叉树吗?
前序+后序,这个组合是无法重建确定的二叉树的。对于满二叉树,利用子树节点的排列顺序能区分开左右子树节点集合,构建是没有问题的。但一旦有单个叶子的节点存在,则无法确定叶子是左儿子还是右儿子。因为无论是前序还是后序序列,都无法体现单个儿子情况下,儿子的位置。前序会将左右子树的点置于节点之后,后序则是将左右子树的点置于节点之前。
举个简单的反例:
给出如下的前序序列和后序序列: preorder: A, B; postorder: B, A能构建的二叉树有两种可能,1.A 是根节点,B 是 A 左儿子; 2.A 是根节点, B 是 A 的右儿子。无法得到一个唯一的结果。
总结
中序遍历配合另外任何一个遍历,能重建二叉树。其他的任意两个序列的组合都不能唯一的确定重建的二叉树。
附:已知后序和中序:
void ReBuild_AftIn(char *pAftOrder, char *pInOrder, int nTreeLen, NODE **pRoot){ if (pAftOrder == NULL || pInOrder == NULL) { return; } NODE *pTemp = new NODE; pTemp->chValue = *pAftOrder; pTemp->pLeft = NULL; pTemp->pRight = NULL; if (*pRoot == NULL) { *pRoot = pTemp; } if (nTreeLen == 1) { return; } int nLeftLen = CharInStrFirstPos(*pAftOrder, pInOrder, nTreeLen); assert(nLeftLen != -1); int nRightLen = nTreeLen - nLeftLen -1; if (nLeftLen > 0) { ReBuild_AftIn(pAftOrder + nRightLen + 1, pInOrder, nLeftLen, &((*pRoot)->pLeft)); } if (nRightLen > 0) { ReBuild_AftIn(pAftOrder + 1, pInOrder + nLeftLen + 1, nRightLen, &((*pRoot)->pRight)); }}
0 0
- 编程之美 3.9 重建二叉树 扩展问题
- 编程之美-重建二叉树扩展问题1 2
- 编程之美3.9 重建二叉树
- [编程之美3.9]重建二叉树
- 编程之美3.9 重建二叉树
- 编程之美 3.9:重建二叉树
- 3.9-编程之美-重建二叉树
- <编程之美>3.9重建二叉树
- 编程之美--3.9 重建二叉树
- 编程之美 3.9 :重建二叉树
- 读书笔记之编程之美 - 3.9 重建二叉树
- 编程之美--重建二叉树
- 重建二叉树(编程之美)
- 编程之美-----重建二叉树
- 《编程之美》重建二叉树
- 编程之美--重建二叉树
- 编程之美-先序中序 重建二叉树
- 编程之美2: 重建二叉树
- WiFi基本知识
- C++ 关键字nothrow
- iOS工程中Xcode出现my mac 64-bit错误
- 使用Kettle 对记录排序并取前面n条记录的方法
- C++11 并发指南七(C++11 内存模型一:介绍)
- 编程之美 3.9 重建二叉树 扩展问题
- MyEclipse添加ibatis DTD文件实现xml的自动提示功能
- cocos2dx手写js绑定C++
- WdatePicker.js 日历点击时,触发自定义方法
- Qt多文档界面应用设计
- 天气预报接口,精确到县级
- PHP_thinkphp框架使用PHPMailer实现发送邮件的功能,以及各种问题解析
- container_of()宏
- Can't bind to local 8601 for debugger