單鏈表的快速排序
首先,很容易想到的是:
要做一輪基準值定位,怎麼做?
要做左子鍊錶和右子鍊錶的遞迴,怎麼做?
第二個問題比較好回答,只要知道子鍊錶的首尾節點,就可以做遞迴了。偽**是:
void
quick_sort_link
(node *start, node *end=
null
);
第乙個問題才是要解決的難題。思路如下:
假設第一輪基準值定位做完了,我們需要有什麼才能繼續進行?
很顯然,需要有左子鍊錶和右子鍊錶的各自的首尾節點。那麼,左鍊錶的首節點和右鍊錶的尾節點,這2個一開始就有了。所以,需要有的是:左子鍊錶的尾節點,和 右子鍊錶的首節點。而這2個節點分別位於基準值節點的左邊和右邊。
這個時候,有乙個思路是:使用2個輔助指標 p1 和 p2.
p1 負責維護左子鍊錶,它是左子鍊錶的最後乙個節點;
p2 負責維護右子鍊錶,它不斷右移:其實,相當於p2在不斷擴充右子鍊錶,而待探索區不斷縮小
當p2在探索區發現大值的時候,只需右移即可,將其納入右子鍊錶的範圍;
當p2發現小值的時候,就要把p1右移乙個(相當於擴大左子鍊錶的範圍),然後交換p1和p2的值(把小值和原來右子鍊錶的最後乙個節點交換),然後p2繼續右移。
到最後,還需要交換基準值和p1的值,因為,基準值從來沒有動過,還在第乙個節點的位置,而p1最終已經指向左子鍊錶的最後乙個位置,因此需要交換它們2個。
所以,**就是
int t = start-
>data;
// 基準值
while
(p2 != end)
p2 = p2-
>next;
}swap
(start-
>data, p1-
>data)
;
問題是:按上面的演算法,初始狀態也是正確的嗎?
這個時候可以舉幾個例子來驗證了!(這是白板程式設計時的重要方法!)
比如:15 -> 1 -> 20, *p1=15, *p2=1,
15 -> 1 -> 20, *p1=1, *p2=20,
15 -> 1 -> 20, *p1=1, *p2=null
此時,需交換start和p1的值,即:
1-> 15 -> 20
驗證成功!
又比如:
10 -> 2 -> 50 -> 3 -> 20, *p1=10, *p2=2, t=10
*p1=2, *p2=2, 10 -> 2 -> 50 -> 3 -> 20,
*p1=2, *p2=50, 10 -> 2 -> 50 -> 3 -> 20,
*p1=2, *p2=3, 10 -> 2 -> 50 -> 3 -> 20,
*p1=50, *p2=3, 10 -> 2 -> 50 -> 3 -> 20,
*p1=3, *p2=20, 10 -> 2 -> 3 -> 50 -> 20,
*p1=3, *p2=null, 10 -> 2 -> 3 -> 50 -> 20,
此時交換p1和start的值
3 -> 2 -> 10 -> 50 -> 20
驗證成功!
再重複一遍,以上乙個要點是,在最後需要交換p1和start的值。
原因是,迴圈結束的時候,p1的值是左子鍊錶的最後乙個節點,它的後面就是右子鍊錶了; 而start的值就是基準值,它一直在第1個節點的位置沒有動過;所以需要交換。
完整的**是:
#include
using
namespace std;
// int array = ; // 12, 13, 14, 23, 34, 45, 54, 89, 99, 100
int array=
;struct node };
void
print_list
(node* head)
if(head && head-
>next ==
null)}
node*
create_list
(int
* array,
int size)
return head;}/*
基準值是start->data;
將原鍊錶看作2個鍊錶:左煉表和右鍊錶,左鍊錶最後乙個節點就是基準值
p1是左鍊錶的最後乙個節點,p2是右鍊錶的最後乙個節點
因此,當遇到大於基準值的時候,p2一直右移;
當遇到小於基準值的時候,p1右移乙個,再交換p1和p2的值,相當於維持了p1和p2的定義
一輪迴圈的最後,p2到達了end的位置,此時,應該交換p1和start節點的值,這時才是真正的一輪處理的結束
下一輪,就遞迴呼叫 qs(start, p1) 和 qs(p1->next, end) 了。
*/void
quick_sort_list
(node* start, node* end=
null
) p2 = p2-
>next;
}swap
(p1-
>data, start-
>data)
;quick_sort_list
(start, p1)
;quick_sort_list
(p1-
>next, end);}
intmain()
(完) 單鏈表快速排序
今天在學習 程式設計師使用演算法 時,看到了單鏈表快排序這一節。初看時感覺程式有很大的問題,但是細細品味之後卻發現程式設計的極為巧妙,同時又深感自己c語言指標知識之不牢固,特別是指標的指標方面的知識。單鏈表的快排序和陣列的快排序基本思想相同,同樣是基於劃分,但是又有很大的不同 單鏈表不支援基於下標的...
單鏈表快速排序
今天在學習 程式設計師使用演算法 時,看到了單鏈表快排序這一節。初看時感覺程式有很大的問題,但是細細品味之後卻發現程式設計的極為巧妙,同時又深感自己c語言指標知識之不牢固,特別是指標的指標方面的知識。單鏈表的快排序和陣列的快排序基本思想相同,同樣是基於劃分,但是又有很大的不同 單鏈表不支援基於下標的...
單鏈表快速排序
今天在學習 程式設計師使用演算法 時,看到了單鏈表快排序這一節。初看時感覺程式有很大的問題,但是細細品味之後卻發現程式設計的極為巧妙,同時又深感自己c語言指標知識之不牢固,特別是指標的指標方面的知識。單鏈表的快排序和陣列的快排序基本思想相同,同樣是基於劃分,但是又有很大的不同 單鏈表不支援基於下標的...