主要是雙軸快速排序,其余再最下面的鏈接中
雙軸快速排序算法思路和三向切分快速排序算法的思路基本一致,雙軸快速排序算法使用兩個軸,通常選取最左邊的元素作為pivot1和最右邊的元素作pivot2。首先要比較這兩個軸的大小,如果pivot1 > pivot2,則交換最左邊的元素和最右邊的元素,已保證pivot1 <= pivot2。雙軸快速排序同樣使用i,j,k三個變量將數組分成四部分
A[L+1, i]是小於pivot1的部分,A[i+1, k-1]是大於等於pivot1且小於等於pivot2的部分,A[j, R]是大於pivot2的部分,而A[k, j-1]是未知部分。和三向切分的快速排序算法一樣,初始化i = L,k = L+1,j=R,k自左向右掃描直到k與j相交為止(k == j)。我們掃描的目的就是逐個減少未知元素,並將每個元素按照和pivot1和pivot2的大小關系放到不同的區間上去。
在k的掃描過程中我們可以對a[k]分為三種情況討論(注意我們始終保持最左邊和最右邊的元素,即雙軸,不發生交換)
(1)a[k] < pivot1 i先自增,交換a[i]和a[k],k自增1,k接着繼續掃描
(2)a[k] >= pivot1 && a[k] <= pivot2 k自增1,k接着繼續掃描
(3)a[k] > pivot2: 這個時候顯然a[k]應該放到最右端大於pivot2的部分。但此時,我們不能直接將a[k]與j的下一個位置a[--j]交換(可以認為A[j]與pivot1和pivot2的大小關系在上一次j自右向左的掃描過程中就已經確定了,這樣做主要是j首次掃描時避免pivot2參與其中),因為目前a[--j]和pivot1以及pivot2的關系未知,所以我們這個時候應該從j的下一個位置(--j)自右向左掃描。而a[--j]與pivot1和pivot2的關系可以繼續分為三種情況討論
3.1)a[--j] > pivot2 j接着繼續掃描
3.2)a[--j] >= pivot1且a[j] <= pivot2 交換a[k]和a[j],k自增1,k繼續掃描(注意此時j的掃描就結束了)
3.3) a[--j] < pivot1 先將i自增1,此時我們注意到a[j] < pivot1, a[k] > pivot2, pivot1 <= a[i] <=pivot2,那么我們只需要將a[j]放到a[i]上,a[k]放到a[j]上,而a[i]放到a[k]上。k自增1,然后k繼續掃描(此時j的掃描就結束了)
注意
1. pivot1和pivot2在始終不參與k,j掃描過程。
2. 掃描結束時,A[i]表示了小於pivot1部分的最后一個元素,A[j]表示了大於pivot2的第一個元素,這時我們只需要交換pivot1(即A[L])和A[i],交換pivot2(即A[R])與A[j],同時我們可以確定A[i]和A[j]所在的位置在后續的排序過程中不會發生變化(這一步非常重要,否則可能引起無限遞歸導致的棧溢出),最后我們只需要對A[L, i-1],A[i+1, j-1],A[j+1, R]這三個部分繼續遞歸上述操作即可。
鏈接地址:


