標籤:style blog color os 資料 2014
題目來源,待字閨中,原創@陳利人 ,歡迎大家繼續關注公眾帳號“待字閨中”
分析:思路和資料的快速排序一樣,都需要找到一個pivot元素、或者節點。然後將數組或者單向鏈表劃分為兩個部分,然後遞迴分別快排。
針對數組進行快排的時候,交換交換不同位置的數值,在分而治之完成之後,資料就是排序好的。那麼單向鏈表是什麼樣的情況呢?除了交換節點值之外,是否有其他更好的方法呢?可以修改指標,不進行數值交換。這可以擷取更高的效率。
在修改指標的過程中,會產生新的頭指標以及尾指標,要記錄下來。在partition之後,要將小於pivot的的部分、pivot、以及大於pivot的部分重新串起來成為一個singly linked list。
在partition時,我們用最後的節點作為pivot。當我們掃描鏈表時,如果節點值大於pivot,將節點移到尾部之後;如果節點小於,保持不變。
在遞迴排序時,我們先調用partition將pivot放到正確的為止並返回pivot,然後,遞迴左邊,遞迴右邊,最後在合成一個單鏈表。
具體代碼如下:
#include <iostream>#include <map>#include <vector>#include <assert.h>using namespace std;struct node{int data;struct node* next;node(int x):data(x),next(NULL){}};node* partition(node* start,node* end,node** newHead,node** newEnd){node* provit = end,*tmp = NULL,*pre = NULL;while(start != provit){if(start->data > provit->data){tmp = start->next;if(pre)pre->next = tmp;start->next = NULL;end->next = start;end = start;start = tmp;}else{if(*newHead == NULL)*newHead = start;pre = start;start = start->next;}}if(*newHead == NULL)*newHead = provit;*newEnd = end;return provit;}node* GetTail(node* head){if(head == NULL)return NULL;while(head->next != NULL)head = head->next;return head;}node* QuickSort(node* head,node* end){if(head == NULL || head == end)return head;node* newHead = NULL,*newEnd = NULL;//此處不能用二維指標,不然partition調用*newHead解引用時會出錯node* provit = partition(head,end,&newHead,&newEnd);if(newHead != provit){node* tmp = newHead;while(tmp->next != provit)tmp = tmp->next;tmp -> next = NULL;newHead = QuickSort(newHead,tmp);tmp = GetTail(newHead);tmp->next = provit;}if(provit != newEnd){provit->next= QuickSort(provit->next,newEnd);}return newHead;}void QuickSort(node** head){if(head == NULL)return;*head = QuickSort(*head,GetTail(*head));}void printLink(node* head){while(head != NULL){cout << head->data <<" ";head = head->next;}cout << endl;}int main(){int n,i,value;node* head,*q;cin >> n;for(i=0;i<n;i++){cin >> value;if(i == 0){head = new node(value);q = head;}else{node* p = new node(value);q->next = p;q = p;}}printLink(head);QuickSort(&head);printLink(head);return 0;}如有錯誤,請指正,謝謝