快速排序使用分治法(Divide and conquer)策略来把一个串行(list)分为两个子串行(sub-lists)。
步骤为:
- 从数列中挑出一个元素,称为 "基准"(pivot),
- 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作。
- 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。
递归的最底部情形,是数列的大小是零或一,也就是永远都已经被排序好了。虽然一直递归下去,但是这个算法总会退出,因为在每次的迭代(iteration)中,它至少会把一个元素摆到它最后的位置去。
以平均性能来说,排序 n 个项目要Θ(n log n)次比较。然而,在最坏的性能下,它需要Θ(n2)次比较。
下面是JAVA示例:
=============================================
import java.util.Comparator; import java.util.Random; public class Quicksort { public static final Random RND = new Random(); private static void swap(Object[] array, int i, int j) { Object tmp = array[i]; array[i] = array[j]; array[j] = tmp; } private static <E> int partition(E[] array, int begin, int end, Comparator<? super E> cmp) { int index = begin + RND.nextInt(end - begin + 1); E pivot = array[index]; swap(array, index, end); for (int i = index = begin; i < end; ++ i) { if (cmp.compare(array[i], pivot) <= 0) { swap(array, index++, i); } } swap(array, index, end); return (index); } private static <E> void qsort(E[] array, int begin, int end, Comparator<? super E> cmp) { if (end > begin) { int index = partition(array, begin, end, cmp); qsort(array, begin, index - 1, cmp); qsort(array, index + 1, end, cmp); } } public static <E> void sort(E[] array, Comparator<? super E> cmp) { qsort(array, 0, array.length - 1, cmp); } }
由于上面的运行起来比较麻烦,本人特写了个简单可以直接运行的,说明问题即可,如有错误请各位指正,共同学习,共同进步:
==========================================================
package org.gameover;
import java.util.Random;
public class SimpleQuickSort {
/**
* @param gameover
*/
/* 交换数组中的两个数 */
public static void swap(int[] array, int a, int b) {
int temp = array[b];
array[b] = array[a];
array[a] = temp;
}
/*
* 把一个数组的给定区间(begin to end )分区,是以这区间的随机一个数(index)进行分区的,
* 分区后,index一边是全比它小的,另一边是全比它大的。
*/
public static int partion(int[] intArray, int begin, int end) {
/* 随机产生给定数组中给定区间(begin to end )之间的一个索引值index。 */
int index = begin + new Random().nextInt(end - begin + 1);
int pivot = intArray[index];
swap(intArray, index, end);
for (int i = index = begin; i < end; i++) {
if (intArray[i] >= pivot) { // 如下升序则改成<=
swap(intArray, index++, i);
}
}
swap(intArray, index, end);
return index;
}
/* 把一个数组的给定区间(begin to end)排序 */
public static void qsort(int[] array, int begin, int end) {
if (begin >= end) {
return;
}
/* 分区后得到分区时的基准值(也就是随机得到的那个值)在分区后在数组中的位置 */
int index = partion(array, begin, end);
/* 然后以这个得到的基准值(index)为中间点,向两边分别递归调用qsort() */
qsort(array, begin, index - 1);
qsort(array, index + 1, end);
}
public static void sort(int[] array) {
int begin = 0;
int end = array.length - 1;
qsort(array, begin, end);
}
/* 测试主程序 */
public static void main(String[] args) {
int[] test = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
sort(test);
for (int temp : test) {
System.out.println(temp);
}
}
}