在nlog(n)時間裏對單鏈表排序

兩個思路:

    快速排序(邏輯是自頂向下)。先劃分排序(一次確定一個位置),再對左邊右邊分別排序,一直到最小粒度;

    歸併排序(邏輯自下而上) 先一直到最小粒度,然後兩兩合併排序,最合合成排序好的鏈表;

1,快速排序

        1)根據劃分位置將鏈表 分成兩部分(左邊小於,右邊大於),遞歸:QuickSort(head,end),時間複雜度logn

                void QuickSort(ListNode *head ,ListNode *end){

                    if (head!=end){

                            ListNode *pivot=Getpartion(head , end);

                            QuickSort(head,pivot);

                            QuickSort(pivot->next,end);

                    }

                }

         調用    QuickSort(head, NULL)   呼應後面的j!=end,方便處理最後一個節點

        2)得到劃分的位置:Getpartion(head,end),這裏取第一個節點作爲默認的劃分節點,劃分之後,右邊全小於該節點,左邊全大於該節點,時間複雜度o(n)

                pivot x x x x x x x x x x x x

                左邊   <=  pivot   <= 右邊

                ListNode *Getpartion(ListNode *head, ListNode *end){

                        ListNode *i,*j;

                        if (head ==Null || end == Null) return;

                        else{     #思想:i,j。i前面的節點包含該節點 都<= pivot , j與i之間的都是>pivot

                            int key=head->vaule;    i=head;    j=head-<next;

                            while (j!=end){

                                if (j->vaule<key){    

                                    i=i->next;                #從第二個節點開始,首節點(這裏指的劃分節點)不動,最後和i交換

                                    swap(i->vaule,j->vaule);

                                }

                                j=j->next;

                            }

                            swap(i->vaule,key);        #將首節點放在應有的位置上

               }

2,歸併排序

    1)將鏈表均分成兩部分,關鍵是找到中間節點(兩個指針,一個走一步,一個走兩步);

        ListNode* Merge(ListNode *head){            #這裏必須返回節點,因爲原來的鏈表的節點被打亂了重新排序了,區別上面只是交換值,如果這裏對兩個鏈表合併排序用交換值得辦法,必須犧牲空間o(n),有序鏈表合併排序不至於這樣做

                ListNode *i,*j;

                i=head;

                h-head;

                if (head == end) return;

                while(j!=end){i=i->next;j=j->next; j=j->next; }

                j=i->next;

                i->next=Null;                                    #這裏使右邊節點的最後一個節點指向Null,左邊的節點默認指向Null

                                                                            會方便 後面是兩個尾部指向Null的鏈表合併

                ListNode *left=Merge(head);

                ListNode *right=Merge(j);

                ListNode *sortlist=MergeSort(left,right);   #將兩條有序的鏈表合併,返回一條排好序的鏈表

                return sortlist

        }   

    2)兩個有序鏈表的合併排序;

        ListNode* MergeSort(ListNode *right ,ListNode *left){

            ListNode *i,*j,*a;

            i=right;

            j=left;

            if (i>value>j->value) { a=left ;  j=j->next;}

            else{a=right;i=i->next;  }

            while(i!=Null && j!=Null}{

                if (i->value>j->value)  {a->next=j ; a=a->next ; j=j->next;}

                else{ a->next=i ; a=a->next ; i=i->next; }

            if (i==Null) while(j!=Null) { a->next=j ; a=a->next ; j=j->next;}

            else(j==Null) while(i!=Null) {a->next=i;a=a->next;i=i->next;}

            return a;

    }

                    

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章