二叉樹-創建、重建、轉化

篇一:二叉樹-遍歷終極版
篇二:二叉樹-創建、重建、轉化
篇三:二叉樹-詳解二叉排序樹
篇四:二叉樹-詳解平衡二叉樹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;
    }
};
發佈了79 篇原創文章 · 獲贊 127 · 訪問量 39萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章