二叉树的创建
以前文章里面提到过二叉树的遍历分三种方式,前序遍历,中序遍历和后序遍历,那么二叉树的构建过程也可以分这三种顺序,最常用的应该是先序创建二叉树,比较符合我们的直观想法。
我在实际中遇到的二叉树的创建问题较少,更多的是给定一个二叉树然后对二叉树进行操作。最近遇到了几个题目,跟二叉树的创建有关,也是考验算法的题目,现在记录一下。
根据中序和后序遍历顺序构建二叉树
这个题目一开始想,既然中序和后序已经给出了,那么二叉树就已经创建好了应该?那就何必再构建一次。不过仔细一想,这是考验我基本算法和代码的能力。
思路如下:
- 先找到后序遍历的最后一个节点D,该节点就是头结点
- 从中序遍历的第一个节点开始迭代,直到找到头结点D,该节点的左边就是左子树,右边就是右子树,并记录下从第一个节点到D节点的长度L。
- 后序遍历的前面一段长度为L的就是左子树,剩下的去掉最后一个节点就是右子树。
- 递归的计算下去,直到所有的节点都处理完毕
借鉴了网上的代码,如下:
TreeNode *createTree(vector<int> &inorder, int inBeg, int inEnd, vector<int> &postorder, int postBeg, int postEnd)
{
if (inBeg > inEnd)
return NULL;
int root = postorder[postEnd];
int index;
for(int i = inBeg; i <= inEnd; i++)
if (inorder[i] == root)
{
index = i;
break;//找到头结点
}
int len = index - inBeg;//计算左子树的节点数目
TreeNode *left = createTree(inorder, inBeg, index - 1, postorder, postBeg, postBeg + len - 1);
TreeNode *right = createTree(inorder, index + 1, inEnd, postorder, postBeg + len, postEnd - 1);
TreeNode *node = new TreeNode(root);
node->left = left;
node->right = right;
return node;
}
TreeNode *buildTree(vector<int> &inorder, vector<int> &postorder) {
if (inorder.size() == 0)
return NULL;
TreeNode *head = createTree(inorder, 0, inorder.size() - 1, postorder, 0, postorder.size() - 1);
return head;
}
根据中序和先序遍历顺序构建二叉树
这个思路是类似的
首先是找到先序遍历的第一个节点,即为root结点,之后在中序遍历中找到头结点D,该节点的左边就是左子树,右边就是右子树,用跟上述类似的递归方法实现。
代码如下:
TreeNode *buildTree(vector<int> &preorder, vector<int> &inorder) {
return create(preorder, inorder, 0, preorder.size() - 1, 0, inorder.size() - 1);
}
TreeNode* create(vector<int>& preorder, vector<int>& inorder, int ps, int pe, int is, int ie){
if(ps > pe){
return nullptr;
}
TreeNode* node = new TreeNode(preorder[ps]);
int pos;
for(int i = is; i <= ie; i++){
if(inorder[i] == node->val){
pos = i;
break;
}
}
node->left = create(preorder, inorder, ps + 1, ps + pos - is, is, pos - 1);
node->right = create(preorder, inorder, pe - ie + pos + 1, pe, pos + 1, ie);
return node;
}
当然也有非递归的实现方法,实现起来稍显麻烦,后续会进行总结。