單鏈表的歸並排序


思路:

  相信大家對數組的歸並排序非常了解,不了解的可以自己百度。本博客只是對單鏈表的歸並排序中的小細節進行闡述.

這個圖,就是一種分治的方式,當遞歸到最底層時,對兩個數進行排序,當回到上一層,其實就得到了,兩個有序的序列,然后再對這兩個序列進行排序並合並成一個新的序列。這樣一層一層的重復相同的操作,就可以得到整個序列的排序!

 

重點:

  對於來兩個有序序列的合並,是這樣合並的。

  先申請一個局部的節點(相當於 表頭 ):然后,比較左右鏈表的最小值,誰最小就把誰拆下來,放在新的鏈表后面。值得注意的是:全過程只是申請了一個表頭節點的內存。這一點在不計算遞歸所使用的內存的話,空間復雜度為O(1)

下面看圖解:

      

然后,注意一下代碼中p的維護,因為p是新鏈表的尾指針!

代碼:

struct ListNode {
    int val;
    ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};
class Solution {
public:
    ListNode *sortList(ListNode *head){
        if (!head || !head->next) return head;        //空鏈表和只有一個元素的鏈表不需要排序

        ListNode *p = head, *q = head->next;
        //找到鏈表的中間位置
        while (q&&q->next){        //快慢指針,注意必須前兩步存在
            p = p->next;
            q = q->next->next;
        }
        ListNode *left = sortList(p->next);        //右鏈表
        p->next = NULL;        //將其斷開,為兩個鏈表
        ListNode *right = sortList(head);
        
        return merge(left, right);
    }

    ListNode *merge(ListNode *left, ListNode *right)
    {
        ListNode dummy(0);        //申請一個假節點
        ListNode *p = &dummy;
        while (left&&right){
            if (left->val < right->val){
                p->next = left;
                left = left->next;
            }
            else{
                p->next = right;
                right = right->next;
            }
            p = p->next;
        }
        if (left)p->next = left;
        if (right)p->next = right;
        return dummy.next;
    }

};

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM