兩個思路:
快速排序(邏輯是自頂向下)。先劃分排序(一次確定一個位置),再對左邊右邊分別排序,一直到最小粒度;
歸併排序(邏輯自下而上) 先一直到最小粒度,然後兩兩合併排序,最合合成排序好的鏈表;
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;
}