篇一:二叉樹-遍歷終極版
篇二:二叉樹-創建、重建、轉化
篇三:二叉樹-詳解二叉排序樹
篇四:二叉樹-詳解平衡二叉樹AVL
篇五:二叉樹-常見簡單算法題
對於二叉樹的創建,一般我們只熟悉最簡單的二叉樹創建方式,即逐個輸入節點,然後按照先序遍歷或者中序、後序遍歷方式來遞歸建立二叉樹。但是,光掌握這個是不夠的,我們還得掌握二叉樹的重建(先序中序重建二叉樹,後序中序重建二叉樹),數組轉換爲二叉樹,鏈表轉換爲二叉樹等等。
1、最簡單的創建方式
我們可以根據先序遍歷遞歸創建二叉樹,當然也可以中序或者後序遍歷方式創建二叉樹。
//創建二叉樹
BTress CreateTree(BTress &T)
{
char a;
cin>>a;
if(a=='0')
T=NULL;
else
{
T=new BNode();
T->data=a;
CreateTree(T->LChild);
CreateTree(T->RChild);
}
return T;
}
2、根據前序序列和中序序列建二叉樹
根據二叉樹的前序後中序遍歷的結果來重建二叉樹。
前序:A B D E H I C F G
中序:D B H E I A F C G
怎麼做了?注意,前序遍歷第一個節點A肯定是根節點;那麼,我們可以在中序遍歷中找到這個根節點A,那麼中序遍歷中根節點A左邊的點(D B H E I)就是A的左子樹的節點,右邊的點(F C G)就是A節點右子樹的節點。再看前序遍歷的節點B,對於節點B也是一樣,中序遍歷中根節點B左邊的點(D)就是B的左子樹的節點,右邊的點(H E I)就是B節點右子樹的節點………
根據上述這種思想遞歸下去,可以逐步找到每個點的位置,然後就可以將樹建立起來,具體看代碼(是leetcode上的題)
代碼:
class Solution {
public:
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder)
{
return buildTreeHelp(preorder,inorder,0,preorder.size()-1,0,inorder.size()-1);
}
TreeNode* buildTreeHelp(vector<int>& preorder, vector<int>& inorder,int pr_s,int pr_e,int in_s,int in_e)
{
if(pr_s>pr_e||in_s>in_e) return NULL;
int pivot=preorder[pr_s];
//找到在中序序列中的位置
int k=0;
for(int i=in_s;i<=in_e;i++)
{
if(inorder[i]==pivot)
{
k=i;
break;
}
}
TreeNode* node = new TreeNode(pivot);
node->left=buildTreeHelp(preorder,inorder,
pr_s+1, pr_s+(k-in_s),
in_s, k-1);
node->right=buildTreeHelp(preorder,inorder,
pr_s+(k-in_s)+1, pr_e,
k+1, in_e);
return node;
}
};
3、根據後序序列和中序序列建二叉樹
後續其實跟前序差不多,只不過是倒着來的,它是先右後左。
class Solution {
public:
TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder)
{
return buildTreeHelp(postorder,inorder,0,postorder.size()-1,0,inorder.size()-1);
}
TreeNode* buildTreeHelp(vector<int>& postorder, vector<int>& inorder,int po_s,int po_e,int in_s,int in_e)
{
if(po_s>po_e||in_s>in_e) return NULL;
int pivot=postorder[po_e];
int k=0;
for(int i=in_s;i<=in_e;i++)
{
if(inorder[i]==pivot)
{
k=i;
break;
}
}
TreeNode* node = new TreeNode(pivot);
node->left=buildTreeHelp(postorder,inorder,
po_s, po_s+k-in_s-1,
in_s, k-1);
node->right=buildTreeHelp(postorder,inorder,
po_e-(in_e-k), po_e-1,
k+1, in_e);
return node;
}
};
4、將有序數組裝換爲平衡二叉樹
既然是平衡二叉樹,那麼對於每個節點,都是左邊的比自己小,右邊的比自己大。因此思路就有了,每次確定節點時,就是中間的節點,這個有些像二分查找。
class Solution {
public:
TreeNode* sortedArrayToBST(vector<int>& nums)
{
return generateBST(0,nums.size()-1,nums);
}
TreeNode* generateBST(int left,int right,vector<int>& nums)
{
if(left>right) return NULL;
int mid=(right+left)/2;
TreeNode*node=new TreeNode(nums[mid]);
node->left=generateBST(left,mid-1,nums);
node->right=generateBST(mid+1,right,nums);
return node;
}
};
5、將有序鏈表轉化爲平衡二叉樹
class Solution {
public:
TreeNode* sortedListToBST(ListNode* head)
{
if(head==NULL) return NULL;
return toBST(head,NULL);
}
TreeNode* toBST(ListNode* head, ListNode* tail)
{
ListNode* slow = head;
ListNode* fast = head;
if(head==tail) return NULL;
while(fast!=tail&&fast->next!=tail)
{
fast = fast->next->next;
slow = slow->next;
}
TreeNode* thead = new TreeNode(slow->val);
thead->left = toBST(head,slow);
thead->right = toBST(slow->next,tail);
return thead;
}
};