基本思想
选择一个基准元素,通常选择第一个元素或者最后一个元素,通过一趟扫描,将待排序列分成两部分,一部分比基准元素小,一部分大于等于基准元素,此时基准元素在其排好序后的正确位置,然后再用同样的方法递归地排序划分的两部分。
Java实现1
//不稳定public class 快速排序 {public static void main(String[] args) {int[] a={49,38,65,97,76,13,27,49,78,34,12,64,1,8};System.out.println("排序之前:");for (int i = 0; i < a.length; i++) {System.out.print(a[i]+" ");}//快速排序quick(a);System.out.println();System.out.println("排序之后:");for (int i = 0; i < a.length; i++) {System.out.print(a[i]+" ");}}private static void quick(int[] a) {if(a.length>0){quickSort(a,0,a.length-1);}}private static void quickSort(int[] a, int low, int high) {if(low<high){ //如果不加这个判断递归会无法退出导致堆栈溢出异常int middle = getMiddle(a,low,high);// 前半部分排序quickSort(a, 0, middle-1);// 后半部分排序quickSort(a, middle+1, high);}}private static int getMiddle(int[] a, int low, int high) {int temp = a[low];//基准元素while(low<high){//找到比基准元素小的元素位置while(low<high && a[high]>=temp){high--;}a[low] = a[high];while(low<high && a[low]<=temp){low++;}a[high] = a[low];}a[low] = temp;return low;}}
Java实现2
/*** 快速排序<br/>* <ul>* <li>从数列中挑出一个元素,称为“基准”</li>* <li>重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分割之后,* 该基准是它的最后位置。这个称为分割(partition)操作。</li>* <li>递归地把小于基准值元素的子数列和大于基准值元素的子数列排序。</li>* </ul>** @param numbers* @param start* @param end*/public static void quickSort(int[] numbers, int start, int end) {if (start < end) {int base = numbers[start]; // 选定的基准值(第一个数值作为基准值)int temp; // 记录临时中间值int i = start, j = end;do {while ((numbers[i] < base) && (i < end))i++;while ((numbers[j] > base) && (j > start))j--;if (i <= j) {temp = numbers[i];numbers[i] = numbers[j];numbers[j] = temp;i++;j--;}} while (i <= j);if (start < j)quickSort(numbers, start, j);if (end > i)quickSort(numbers, i, end);}}
Java实现3
public class QuickSort<T extends Comparable<T>> {private static final Random RAND = new Random();public static enum PIVOT_TYPE {FIRST, MIDDLE, RANDOM}public static PIVOT_TYPE type = PIVOT_TYPE.RANDOM;private QuickSort() { }public static <T extends Comparable<T>> T[] sort(PIVOT_TYPE pivotType, T[] unsorted) {int pivot = 0;if (pivotType == PIVOT_TYPE.MIDDLE) {pivot = unsorted.length/2;} else if (pivotType == PIVOT_TYPE.RANDOM) {pivot = getRandom(unsorted.length);}sort(pivot, 0, unsorted.length - 1, unsorted);return unsorted;}private static <T extends Comparable<T>> void sort(int index, int start, int finish, T[] unsorted) {int pivotIndex = start + index;T pivot = unsorted[pivotIndex];int s = start;int f = finish;while (s <= f) {while (unsorted[s].compareTo(pivot) < 0)s++;while (unsorted[f].compareTo(pivot) > 0)f--;if (s <= f) {swap(s, f, unsorted);s++;f--;}}if (start < f) {pivotIndex = getRandom((f - start) + 1);sort(pivotIndex, start, f, unsorted);}if (s < finish) {pivotIndex = getRandom((finish - s) + 1);sort(pivotIndex, s, finish, unsorted);}}private static final int getRandom(int length) {if (type == PIVOT_TYPE.RANDOM && length > 0)return RAND.nextInt(length);if (type == PIVOT_TYPE.FIRST && length > 0)return 0;return length / 2;}private static <T extends Comparable<T>> void swap(int index1, int index2, T[] unsorted) {T index2Element = unsorted[index1];unsorted[index1] = unsorted[index2];unsorted[index2] = index2Element;}}
总结
快速排序是不稳定的排序。
- 快速排序的时间复杂度为O(nlogn)。
- 当n较大时使用快排比较好,当序列基本有序时用快排反而不好。
