目錄
一、概述
在計算機科學中,二叉樹是每個結點最多有兩個子樹的樹結構。通常子樹被稱作“左子樹”(left subtree)和“右子樹”(right subtree)。二叉樹常被用於實現二叉查找樹和二叉堆。
一棵深度爲k,且有2^k-1個結點的二叉樹,稱爲滿二叉樹。這種樹的特點是每一層上的結點數都是最大結點數。而在一棵二叉樹中,除最後一層外,若其餘層都是滿的,並且或者最後一層是滿的,或者是在右邊缺少連續若干結點,則此二叉樹爲完全二叉樹。具有n個結點的完全二叉樹的深度爲floor(log2n)+1。深度爲k的完全二叉樹,至少有2k-1個葉子結點,至多有2k-1個結點。
(1)前序遍歷
a、訪問根節點;b、前序遍歷左子樹;c、前序遍歷右子樹。
(2)中序遍歷
a、中序遍歷左子樹;b、訪問根節點;c、中序遍歷右子樹。
(3)後序遍歷
a、後序遍歷左子樹;b、後續遍歷右子樹;c、訪問根節點。
二、題目
// 3
// / \
// 9 20
// / \
// 15 7
//inorder = [9,3,15,20,7]
//postorder = [9,15,7,20,3]
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
三、實戰
1、思路
中序遍歷和後序遍歷還原二叉樹思想如下:
a、根據後序遍歷結果,最後一個元素爲二叉樹的根結點;
b、觀察中序遍歷結果,根結點左側的爲左子樹;根結點右側的爲右子樹
c、上面的過程是遞歸的。先從postorder結果中找到當前樹的根結點(postorder的最後一個元素),然後使用該值在中序遍歷結果中找到數的左右子樹和根節點(3爲根節點 ,9爲左子樹,15,50,7爲右子樹),由於已經根據中序遍歷結果知道左子樹和有子樹的節點個數進一步也可以在後序遍歷結果中找到左右子樹(9位左子樹,15,7,20爲右子樹,3爲根節點)。最後劃分爲左右子樹,再進入左子樹重複上面的過程,最後進入右子樹重複上面的過程,最終還原一棵樹
2、實現
TreeNode* buildTree_help(vector<int>& inorder, vector<int>& postorder, int instart, int inend, int poststart, int postend)
{
if (poststart >= postend)
{
return NULL;
}
int nl = inend - instart;
int k = 0;
for (int i = instart; i <instart + nl; ++i)
{
if (inorder[i] == postorder[postend-1])
break;
k++;
}
TreeNode*left = buildTree_help(inorder, postorder, instart, instart + k, poststart, poststart + k);
TreeNode *right= buildTree_help(inorder, postorder, instart+k+1,inend, poststart + k, postend-1);
TreeNode *p = new TreeNode(postorder[postend - 1]);
p->left = left;
p->right = right;
}
TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder)
{
return buildTree_help(inorder, postorder, 0, inorder.size() , 0, postorder.size());
}
四、調用
int main()
{
std::vector<int>inorder = { 9,3,15,20,7 };
std::vector<int> postorder = { 9,15,7,20,3 };
TreeNode* p = buildTree(inorder, postorder);
return 0;
}
五、總結
二叉樹的一些算法很有意思,很值得研究,重點是先找到當前樹的根結點,然後劃分爲左右子樹,再進入左子樹重複上面的過程,最後進入右子樹重複上面的過程,最終還原一棵樹。