普通快速排序一次把数据划分成两部分,两部分再分别递归,两枢轴,就是两个结点,把数据划分成三部分,三部分再分别递归,可参考下图
left part center part right part +--------------------------------------------------------------+ | < pivot1 | pivot1 <= && <= pivot2 | > pivot2 | +--------------------------------------------------------------+ ^ ^ | | less great
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
划分成三部分:leftpart:x<p1,centerpart:p1<=x<=p2,rightpart:x>p2leftpart:x<p1,centerpart:p1<=x<=p2,rightpart:x>p2
程序中给的下图
/* * Partitioning: * * left part center part right part * +--------------------------------------------------------------+ * | < pivot1 | pivot1 <= && <= pivot2 | ? | > pivot2 | * +--------------------------------------------------------------+ * ^ ^ ^ * | | | * less k great * * Invariants: * * all in (left, less) < pivot1 * pivot1 <= all in [less, k) <= pivot2 * all in (great, right) > pivot2 * * Pointer k is the first index of ?-part. */
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
(2)ak < p1 && ak >p2ak这个数放到对应的great的位置
程序中是先找到:A[great] < pivot2 的位置
while (A[great] > pivot2) { // 找到不满足条件的位置 if (great-- == k) { System.out.println("outer"); break outer; } }
- 1
- 2
- 3
- 4
- 5
- 6
若成立:这个时候说明great位置的数应该在 在< p1 的部分
if (A[great] < pivot1) { // a[great] <= pivot1, A[k] = A[less]; // less放到 k的位置, k 位置的元素数保存在 ak中 A[less] = A[great]; // great 放到less的位置 ++less; // 更新 less } else { // pivot1 <= a[great] <= pivot2 A[k] = A[great]; }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
最后还有这个
A[great] = ak; // ak 放到 great位置 --great;
- 1
- 2
若:A[great] >= pivot1 又:A[great] <= pivot2
A[k] = A[great];
A[great] = ak
就这样
图中对run数组还没有理解,没有细画,在归并排序中会调用到快排的过长也没有画出来,因为这里都用到run数组,表示没理解。
下图中不是进行归并,而是进行快排递归
由于p1 p2 两个值取得的左右端点的值,同时没有做相等判断,所有程序对没有相等数据可以实现排序
package alg.sort; public class DualQuickSort { public void dualQuickSort(int[] A,int left,int right){ if(left>=right) { // System.out.println(left+"\t"+right); return; } if(A[left]>A[right]) { swap(A,left,right); } int less = left; int great = right; int pivot1 = A[left]; int pivot2 = A[right]; while (A[++less] < pivot1); while (A[--great] > pivot2); /* * Partitioning: * * left part center part right part * +--------------------------------------------------------------+ * | < pivot1 | pivot1 <= && <= pivot2 | ? | > pivot2 | * +--------------------------------------------------------------+ * ^ ^ ^ * | | | * less k great * * Invariants: * * all in (left, less) < pivot1 * pivot1 <= all in [less, k) <= pivot2 * all in (great, right) > pivot2 * * Pointer k is the first index of ?-part. */ outer: for(int k = less - 1;++k<= great;){ int ak = A[k]; if(ak<pivot1){ // ak 小于 p1 swap(A,k,less); // 交换 less++; }else if(ak>pivot2){ // ak > p2 while (A[great] > pivot2) { // 找到不满足条件的位置 if (great-- == k) { System.out.println("outer"); break outer; } } if (A[great] < pivot1) { // a[great] <= pivot1, A[k] = A[less]; // less放到 k的位置, k 位置的元素数保存在 ak中 A[less] = A[great]; // great 放到less的位置 ++less; // 更新 less } else { // pivot1 <= a[great] <= pivot2 A[k] = A[great]; } /* * Here and below we use "a[i] = b; i--;" instead * of "a[i--] = b;" due to performance issue. */ A[great] = ak; // ak 放到 great位置 --great; } // 其他情况就是中间位置,不用考虑 } System.out.println("left :"+left+" less " + less + " great" + great+" right "+ right); Print.printArray(A); dualQuickSort(A,left,less-1); dualQuickSort(A,less,great); dualQuickSort(A,great+1,right); } public void swap(int[] A,int i,int j){ int t = A[i]; A[i] = A[j]; A[j] = t; } public static void main(String[] args){ int[] A = new int[]{13,3,65,97,76,10,35,71,5,7,3,27,49}; Print.printArray(A); DualQuickSort dualQuickSort = new DualQuickSort(); int l = 0; int r = A.length -1; dualQuickSort.dualQuickSort(A,l,r); Print.printArray(A); } }