大家可能對一維陣列的快速排序和歸併排序比較熟悉,單鏈表的快速排序和歸併排序本質上與一維陣列相同,但存在細微差別。
先介紹一下單鏈表的快速排序。快速排序的基本函式是partition函式,其功能是以乙個參考節點的內容為參考值,將原陣列的元素進行移位,移位結果
使得參考值節點左側的節點值均小於等於該參考值,參考值節點右側的節點值均大於大於該參考值。很多人比較熟悉的paitition演算法是使用兩個指標分別指向
陣列的頭、尾節點,然後使這兩個節點不斷往中間靠攏的演算法。但是這種演算法對單鏈表並不適用,因為無法通過單鏈表的尾節點直接找到尾節點的前乙個節點。
於是,好多人可能覺得單鏈表無法用快速排序演算法排序。其實不然。還有一種相同複雜度的partition演算法,演算法中參考指標只朝鍊錶的方向移動,使用該partition
演算法即可實現單鏈表的快速排序。
該partition演算法的基本思路為:
1、將鍊錶的第乙個節點的值作為參考值,設定兩個指標p0和p1。p0初始指向鍊錶的第乙個節點,p1初始指向鍊錶的第二個節點。
從鍊錶的首節點到p0節點,這些節點的值都小於等於參考值;p1表示最新遍歷的節點。
2、p1不斷先前推進,每當p1所指節點的值小於參考值,說明新找到乙個值小於參考值的節點,將p0向前推進,然後該節點的值與p0的值交換。從而使得
已經處在正確位置的值小於等於參考值的節點數增加。由於p1每次找到乙個值小於參考值的節點,都會將該節點的值與當前狀態下最前面的乙個值大於參考值
的節點值進行交換。因此,當p1推進到鍊錶的末尾時,就可以保證鍊錶的首節點到p0節點的節點值均小於等於參考值;p0-next到鍊錶末尾的節點值均大於等於
參考值。
3、由於p0的節點值有可能小於參考值。因此,需要將p0的值與鍊錶的首節點的值進行交換。
**如下:
#includeusing namespace std;
struct node
;void qsort(node *head, int n);
int main()
pnode=phead;
node *temp=null;
for(int i=1; i>temp->data;
temp->next=null;
pnode->next=temp;
pnode=temp;
} qsort(phead, n);
pnode=phead;
while(pnode!=null)
coutint ref;
ref=front->data;
int count=1;
int frontnum=0;
while(countdatanext;
++frontnum;
if(front!=rear)
}rear=rear->next;
++count;
} int temp=front->data;
front->data=head->data;
head->data=temp;
qsort(head, frontnum);
qsort(front->next, n-frontnum-1);
}
下面再介紹一下單鏈表的歸併排序方法。
歸併排序的基本思想是分治。將長度為n的陣列等分成前後兩端陣列。先分別對錢後兩端陣列進行歸併排序,然後將前後兩端已經
排好序的子陣列進行合併。 一維陣列可以直接跳過下標以o(1)的複雜度找到前後兩端陣列的分界線,而鍊錶只能通過逐個節點遍歷的方法找到前後
兩端陣列的分界線。想要找到單鏈表的中間節點,可以使用兩個指標。乙個指標p1以2步長向前推進,另乙個指標p0以一步長向前推進。當p1移動到
鍊錶末尾時,p0即鍊錶的中間節點。
實現**如下:
#includeusing namespace std;
struct node
;node* mergesort(node *head, node *rear);
int main()
pnode=phead;
node *temp=null;
for(int i=1; i>temp->data;
temp->next=null;
pnode->next=temp;
pnode=temp;
} phead=mergesort(phead, pnode);
pnode=phead;
while(pnode!=null)
coutif(head==rear)
return head;
node *p0=head, *p1=head;
while(p1->next!=null) }
node *head1=p0->next;
node* pfront=mergesort(head, p0);
node* pbehind=mergesort(head1, rear);
node *reshead=null;
if(pfront->data < pbehind->data)
else
node *ptemp=reshead;
while(pfront!=null && pbehind!=null)
else
}if(pfront!=null)
ptemp->next=pfront;
else
ptemp->next=pbehind;
return reshead;
}
單鏈表歸併排序
1 對於鍊錶來說,由於其元素的訪問只能是順序訪問,而快速排序是改進後的氣泡排序,需要隨機訪問資料,不合適。採用歸併排序方式對鍊錶元素進行訪問 2 需要的步驟 1 分割 將一段鍊錶分成兩部分 2 排序 將兩端已經有序的鍊錶合併 3 分治遞迴 遞迴操作 將鍊錶plist分割,並把分割後的兩段鍊錶第乙個元...
單鏈表的歸併排序
題目 單鏈表的歸併排序 思路 首先找到鍊錶的中間節點,將原始鍊錶一分為二,遞迴進行該操作,直到被劃分的兩個鍊錶包含的節點少於等於1個,即該次劃分後兩個鍊錶已經有序。然後依次合併兩個有序的鍊錶,直到所有劃分都合併完,即排序完畢。主要編寫將兩個有序鍊錶合併為乙個有序鍊錶的函式。includeusing ...
單鏈表的歸併排序
question 148.sort list sort a linked list in o n log n time using constant space complexity.中文 使用恆定的空間複雜度排序乙個鍊錶,要求時間複雜度是o nlogn 我們知道題目的要求是時間複雜度是o nlog...