何时使用递归解决问题?-重建二叉树
2016-04-15 16:51
471 查看
将主问题分割成小问题的时,当发现小问题与主问题在本质上是一样的,即小问题重复主问题分割成小问题这个步骤时,要开始处理这个小问题,就在此处,调用递归函数。分割成更小的问题,就要用递归方法解决。典型的应用:根据二叉树的前序遍历和中序遍历,创建一个二叉树结构问题。
思路如下:第一:根据前序遍历的第一个结点值为根结点,然后遍历中序遍历的输出,找到这个根节点在中序遍历中的位置,记录此位置pos,此时,在中序遍历左边的全部是根节点中左子树上面的结点,右边是根节点中右子树的结点。
第二:根据pos,在前序遍历中,第二个结点到pos处的都属于左子树的结点,pos+1处到结尾属于右子树的结点。根据中序遍历的输出,根结点位置到左边第一个结点的所有结点为一个整体,此时,前序遍历中第二个结点到pos作为一个整体,以此两个视为一个前序遍历和中序遍历输出的子问题,右子树情况类似,不断这样重复划分,此时就应用递归解决问题。代码如下:
思路如下:第一:根据前序遍历的第一个结点值为根结点,然后遍历中序遍历的输出,找到这个根节点在中序遍历中的位置,记录此位置pos,此时,在中序遍历左边的全部是根节点中左子树上面的结点,右边是根节点中右子树的结点。
第二:根据pos,在前序遍历中,第二个结点到pos处的都属于左子树的结点,pos+1处到结尾属于右子树的结点。根据中序遍历的输出,根结点位置到左边第一个结点的所有结点为一个整体,此时,前序遍历中第二个结点到pos作为一个整体,以此两个视为一个前序遍历和中序遍历输出的子问题,右子树情况类似,不断这样重复划分,此时就应用递归解决问题。代码如下:
struct BinaryTreeNode { int m_nValue; BinaryTreeNode *m_pLeft; BinaryTreeNode *m_pRight; }; BinaryTreeNode* ConstructCore(int* startPreorder, int* endPreorder, int* startInorder, int* endInorder); BinaryTreeNode* Construct(int* preorder, int* inorder, int length) { if(preorder == NULL || inorder == NULL || length <= 0) return NULL; return ConstructCore(preorder, preorder + length - 1, inorder, inorder + length - 1); } BinaryTreeNode* ConstructCore ( int* startPreorder, int* endPreorder, int* startInorder, int* endInorder) { // 前序遍历序列的第一个数字是根结点的值 int rootValue = startPreorder[0]; BinaryTreeNode* root = new BinaryTreeNode(); root->m_nValue = rootValue; root->m_pLeft = root->m_pRight = NULL; if(startPreorder == endPreorder) { if(startInorder == endInorder && *startPreorder == *startInorder) return root; else throw std::exception("Invalid input."); } // 在中序遍历中找到根结点的值 int* rootInorder = startInorder; while(rootInorder <= endInorder && *rootInorder != rootValue) ++ rootInorder; if(rootInorder == endInorder && *rootInorder != rootValue) throw std::exception("Invalid input."); int leftLength = rootInorder - startInorder; int* leftPreorderEnd = startPreorder + leftLength; if(leftLength > 0) { // 构建左子树 root->m_pLeft = ConstructCore(startPreorder + 1, leftPreorderEnd, startInorder, rootInorder - 1); } if(leftLength < endPreorder - startPreorder) { // 构建右子树 root->m_pRight = ConstructCore(leftPreorderEnd + 1, endPreorder, rootInorder + 1, endInorder); } return root; }
相关文章推荐
- clientX,screenX,pageX,offsetX的异同 【转载】
- (转)js activexobject调用客户机exe文件
- Eclipse开发环境下,部署和配置svn的整个过程
- 各种Android控件实用
- spring 注解 出现'sessionFactory' or 'hibernateTemplate' is required异常
- 冒泡排序和快速排序以及Android的collections.sort排序
- kafka学习笔记
- centos+xfceroot用户创建系统解决chrome问题;
- Java 正则中的(.*?)vs(.*)
- 神奇彩带KMP
- c#连接SFTP上传文件
- css与 js动画 优缺点比较
- 【QT】:QT实现一个信号与多个槽的关联和实现多个信号与一个槽的关联
- TestNG使用方法
- Android系统图册更新保存的图片
- cocos2d-x自制工具07:打印cocos2d-x的节点树
- 关于最大、最小比例尺
- Win7 VS2015环境使用qt-msvc2015-5.6.0
- yii使用bootstrap分页样式
- Struts2中关于"There is no Action mapped for namespace / and action name"错误