重建二叉树

来源:互联网 发布:笑傲江湖ol 知乎 编辑:程序博客网 时间:2024/06/05 14:58

题目:由前序遍历和中序遍历重建二叉树

前序序列:1 2 3 4 5 6 

中序序列:3 2 4 1 6 5

思路:每次以前序遍历序列的第一个数作为根结点,再在中序遍历序列里边找到根结点。根据中序遍历的特点我们可以知道,只有左子树全部访问完之后才会访问根结点,所以我们找到根结点之后,发现根结点之前的数都是根结点的左子树的所有结点,右边的数都是根结点右子树的所有结点。那么,可以以根结点为中心,将中序遍历序列分为两部分,左子树和右子树。

同时将与左子树等长的那部分前序序列作为新的前序序列,右子树也一样。将前序序列和中序序列每次都截成两部分,作为递归入口点进行递归。递归的出口就是找到叶子结点或者说新区间里边只剩下一个值时。

这道题再递归的时候,一定要注意边界条件的更新,如果是数组,要注意下标问题,vector则要弄明白end()的返回值。


#pragma oncetemplate<class T>struct BinaryTreeNode{T _data;BinaryTreeNode<T>* _left;BinaryTreeNode<T>* _right;BinaryTreeNode(const T& d): _data(d), _left(NULL), _right(NULL){}};template<class T>class ConstructTree{public:typedef BinaryTreeNode<T> Node;ConstructTree(T* preOrder, T* inOrder, size_t length){if (preOrder == NULL || inOrder == NULL  || length <= 0)_root = NULL;else_root =  _ConstructTree(preOrder, preOrder + length - 1, inOrder, inOrder + length - 1);}protected:Node* _ConstructTree(T* startPre, T* endPre, T* startIn, T* endIn){//前序遍历序列的第一个数是根节点的值Node* root = new Node(startPre[0]);//递归结束条件,找到叶子结点,也就是区间缩小到只剩下一个值if (startPre == endPre){if (startIn == endIn && *startPre == *startIn)return root;elsethrow exception("invalid input");}//在中序遍历中找到根结点T* rootIn = startIn;while (rootIn <= endIn && *rootIn != root->_data){++rootIn;}//已经遍历完还没右找到根结点if (rootIn == endIn && *rootIn != root->_data)throw exception("invalid input");//已经找到根节点size_t leftLengthIn = rootIn - startIn;//更新前序遍历的区间范围T* newEndPro = startPre + leftLengthIn;//构建左子树if (leftLengthIn > 0){root->_left = _ConstructTree(startPre + 1, newEndPro, startIn, rootIn - 1);}//构建右子树if (leftLengthIn < endPre - startPre){root->_right = _ConstructTree(newEndPro + 1, endPre, rootIn + 1, endIn);}return root;}protected:Node* _root;};void Test(){int a[] = { 1, 2, 4, 7, 3, 5, 6, 8 };int b[] = { 4, 7, 2, 1, 5, 3, 8, 6 };ConstructTree<int> t1(a, b, 8);}

原创粉丝点击