根据前序和中序,构建二叉树
2014-04-16 11:06
417 查看
在学习数据结构的时候,经常会考到用前中后序三者之二来重构二叉树或者得到另外一个未知的遍历顺序
往往对着图和数字我们可以轻松地把树画出来,但是如果要我们用代码实现它,又要怎么做呢?
其实过程是一样的,只要牢记前中后序的产生过程,逆向推导,加以严谨的程序控制就可以完成了。
前序遍历:也叫先根遍历,即先访问树的根节点,然后再依次递归访问左子树和右子树
中序遍历:也叫中根遍历,即先访问左子树,然后访问根节点,最后再访问右子树
假设我们的树长这个样子
那么就可以得到:
前序遍历:1 2 4 7 5 3 6 8
中序遍历:4 7 2 5 1 3 8 6
下一步用代码重构
定义如下数据结构:树的节点
观察前序和中序的产生过程,不难发现:
前序的第一个元素就是根节点
而相应的根节点则在中序中间(不一定是正中间),中序中,根节点位置的左边都属于左子树,而右边则属于右子树
并且可以发现,前序中,是左子树先“扎堆”,然后是右子树”扎堆“,也即不会发生交叉现象
以我们的数据为例,从前序可以知道 1 就是根节点,从中序可以得知,4,7,2,5 都是在左子树中,1,3,8,6 则都在右子树中。
看看现在我们得到的有什么:
一个简单通过前序就能拿到的根节点
通过遍历可以从中序中划分出来的左子树节点群和右子树节点群
通过以上两步,可以确定左右子树各自的前中序,比如左子树,他的前序是 2,4,7,5 ,而其中序是 4,7,2,5
于是可以想到,可以用 递归 来重构树了!
从根节点出发,分别递归设置左右子树,当跳出递归时,整颗树都重构完毕
代码实现如下:
小结:要深刻理解前中后序的产生过程及其特点,这是构建树的关键。要理解用递归来处理树的问题,大而化小,分而治之
往往对着图和数字我们可以轻松地把树画出来,但是如果要我们用代码实现它,又要怎么做呢?
其实过程是一样的,只要牢记前中后序的产生过程,逆向推导,加以严谨的程序控制就可以完成了。
前序遍历:也叫先根遍历,即先访问树的根节点,然后再依次递归访问左子树和右子树
中序遍历:也叫中根遍历,即先访问左子树,然后访问根节点,最后再访问右子树
假设我们的树长这个样子
那么就可以得到:
前序遍历:1 2 4 7 5 3 6 8
中序遍历:4 7 2 5 1 3 8 6
下一步用代码重构
定义如下数据结构:树的节点
struct BTreeNode { int m_ivalue; BTreeNode* m_pleft; BTreeNode* m_pright; };
观察前序和中序的产生过程,不难发现:
前序的第一个元素就是根节点
而相应的根节点则在中序中间(不一定是正中间),中序中,根节点位置的左边都属于左子树,而右边则属于右子树
并且可以发现,前序中,是左子树先“扎堆”,然后是右子树”扎堆“,也即不会发生交叉现象
以我们的数据为例,从前序可以知道 1 就是根节点,从中序可以得知,4,7,2,5 都是在左子树中,1,3,8,6 则都在右子树中。
看看现在我们得到的有什么:
一个简单通过前序就能拿到的根节点
通过遍历可以从中序中划分出来的左子树节点群和右子树节点群
通过以上两步,可以确定左右子树各自的前中序,比如左子树,他的前序是 2,4,7,5 ,而其中序是 4,7,2,5
于是可以想到,可以用 递归 来重构树了!
从根节点出发,分别递归设置左右子树,当跳出递归时,整颗树都重构完毕
代码实现如下:
BTreeNode* build(int* preOrder, int* inOrder, int length) { if (preOrder == NULL || inOrder == NULL || length == 0) //前中序为空 return NULL; else return buildcore(preOrder, preOrder + length - 1, inOrder, inOrder + length - 1); } BTreeNode* buildcore(int* preOrderStart, int* preOrderEnd, int* inOrderStart, int* inOrderEnd) { BTreeNode* root = new BTreeNode(); //new 一个根节点,在递归过程中也可以称为子树根节点 root->m_ivalue = *preOrderStart; root->m_pleft = root->m_pright = NULL; //初始化为NULL if (preOrderStart == preOrderEnd){ if (inOrderEnd == inOrderStart && *preOrderStart == *inOrderStart) return root; else throw std::exception("Invalid input"); } int* rootInOrder = inOrderStart; //在中序中遍历查找根所在的位置 while (rootInOrder != inOrderEnd && *rootInOrder != root->m_ivalue) ++rootInOrder; if (rootInOrder == inOrderEnd && *rootInOrder != root->m_ivalue) throw std::exception("Invalid input"); int leftLength = rootInOrder - inOrderStart; int* leftPreOrderEnd = preOrderStart + leftLength; //构建左子树 if (leftLength > 0){ root->m_pleft = buildcore(preOrderStart + 1, leftPreOrderEnd, inOrderStart, rootInOrder - 1); } //构建右子树 if (leftLength < inOrderEnd - inOrderStart){ root->m_pright = buildcore(leftPreOrderEnd + 1, preOrderEnd, rootInOrder + 1, inOrderEnd); } return root; }
小结:要深刻理解前中后序的产生过程及其特点,这是构建树的关键。要理解用递归来处理树的问题,大而化小,分而治之
相关文章推荐
- 【构建二叉树】01根据前序和中序序列构造二叉树【Construct Binary Tree from Preorder and Inorder Traversal】
- 根据二叉树的前序和中序构建二叉树
- 二叉树系列——根据前序和中序、中序和后序构建二叉树
- 根据前序和中序构建二叉树
- 剑指offer04--根据前序和中序构建二叉树
- Offer题6 根据前序和中序构建二叉树
- 根据树的后序和中序序列或者前序和中序序列构建二叉树,
- 根据前序和后序构建二叉树
- 根据前序和中序重建二叉树
- 根据二叉树的前序和中序序列来重建二叉树
- 根据中序序列与后序序列构建二叉树
- 树的学习——(递归构建二叉树、递归非递归前序中序后序遍历二叉树、根据前序序列、中序序列构建二叉树)
- 已知二叉树的前序和中序遍历,构建该二叉树
- 根据前序和中序数组构造二叉树(递归方法)
- 【构建二叉树】02根据中序和后序序列构造二叉树【Construct Binary Tree from Inorder and Postorder Traversal】
- Python练手之根据前序和中序&根据中序和后序重建二叉树,输出前序、中序和后序遍历结果
- LeetCode:105_Construct Binary Tree from Preorder and Inorder Traversal | 根据前序和中序遍历构建二叉树 | Medium
- 剑指offer_根据前序和中序确定二叉树
- POJ 2255 根据二叉树的前序和中序序列来重建二叉树
- 剑指offer刷题之c++实现的根据二叉树的前序和中序遍历重建二叉树