leetcode算法題--排序鏈表★

原題鏈接:https://leetcode-cn.com/problems/sort-list/

1、歸併排序(遞歸版)

ListNode* sortList(ListNode* head) {
    if(head==NULL||head->next==NULL) return head;
    ListNode *p=head,*q=head->next;
    while(q!=NULL&&q->next!=NULL){//找出鏈表中點
        p=p->next;
        q=q->next->next;
    }
    ListNode *mid=p->next;
    p->next=NULL;
    ListNode *left=sortList(head);//將左右鏈表分別遞歸
    ListNode *right=sortList(mid);
    ListNode *dummy=new ListNode;
    ListNode *t=dummy;
    while(left!=NULL&&right!=NULL){//將左右兩邊鏈表排序
        if(left->val>right->val){
            t->next=right;
            right=right->next;
        }else{
            t->next=left;
            left=left->next;
        }
        t=t->next;
    }
    t->next=left!=NULL?left:right;
    return dummy->next;
}

2、歸併排序(非遞歸版)

模擬歸併排序的分隔部分,初始合併單元長度len=1,每一輪len=len*2,依次合併。
在這裏插入圖片描述

ListNode *sortList(ListNode* head){
    ListNode *p=head;
    int length=0;
    while(p!=NULL){
        p=p->next;
        length++;
    }
    ListNode *dummy=new ListNode;//啞頭節點
    dummy->next=head;
    int len=1;
    while(len<length){
        ListNode *pre=dummy;//用於合併的輔助頭部
        ListNode *h=dummy->next;
        while(h!=NULL){
            ListNode *h1=h;
            int i=len;
            while(h!=NULL&&i>0){
                h=h->next;
                i--;
            } 
            if(i>0) break;//如果鏈表剩餘個數少於len,則無需合併環節,直接break,執行下一輪合併
            ListNode *h2=h;
            i=len;
            while(h!=NULL&&i>0){
                h=h->next;
                i--;
            }
            int c1=len;
            int c2=len-i;//若h2存在,但以h2爲頭部的剩餘個數少於len,也執行合併環節,h2單元長度爲c2=len-i
            while(c1>0&&c2>0){
                if(h1->val<h2->val){
                    pre->next=h1;
                    h1=h1->next;
                    c1=c1-1;
                }else{
                    pre->next=h2;
                    h2=h2->next;
                    c2=c2-1;
                }
                pre=pre->next;
            }
            pre->next=c1>0?h1:h2;
            while(c1>0||c2>0){
                pre=pre->next;
                c1=c1-1;
                c2=c2-1;
            }
            pre->next=h;//合併完後,修改新的合併單元尾部pre指針指向下一個合併單元頭部h
        }
        len=len*2;
    }
    return dummy->next;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章