对于一棵二叉树而言,遍历方式基本分为三种:前序、中序、后序。
想要通过已有的遍历顺序重建二叉树,需要两种遍历方式,其中必须包括中序遍历。这是因为前序和后序只能提供哪个是根节点(两种方式提供的信息其实是一样的,只不过提供方式稍有不同),不能提供左右子树的信息,想要把左右子树区分开,一定要用中序遍历。因为在中序遍历中,知道了根节点的位置,那么它左边就都是左子树的节点,右边就都是右子树的节点,想要知道根节点的位置,就需要知道根节点是哪个,也就需要前序或者后序遍历的了。
一、已知前序、中序
在前序遍历中,第一个数,就是根节点,后边的是左子树和右子树,只不过分不出从哪里开始是右子树。每次从前序遍历中取出第一个节点(也就是根节点)后,在中序遍历中找出根节点所在位置,左边的是左子树(这样就知道左子树有多少个节点点了,也就知道前序遍历中,到哪里为止,是左子树了),右边的是右子树,然后递归就可以完成二叉树的构建。
TreeNode* buildTree(vector<int>& pre, vector<int>& in) {
return helper(pre, 0, pre.size(), in, 0, in.size());
}
TreeNode* helper(const vector<int>& pre, int i, int j, const vector<int>& in, int ii, int jj) {
// tree 8 4 5 3 7 3
// preorder 8 [4 3 3 7] [5]
// inorder [3 3 4 7] 8 [5]
// 每次从 pre 头部取一个值 mid, 作为树的根节点
// 检查 mid 在 in 中的位置, 则 mid 前面部分将作为树的左子树, 右边作为树的右子树
if(i >= j || ii >= j)
return nullptr;
const int mid = pre[i];
const