一、基本思想
通过使用一个基准值将列表分为2个子列表,具体的过程是:
将基准值放在正确的位置上,在一个子列表中放入小于基准值的元素,另一个子列表中放入大于基准值的元素。
这就是快速排序(Quick Sort)的思想。
快排算法提供了目前已知最快的排序技术,除了某些极其特殊的情况下之外,快速排序徐几乎适用于所有场合。
二、算法描述
快速排序使用一系列递归调用将列表分为若干越来越小的子列表,这些子列表位于基准值(pivot)左右。每个递归步骤根据作为列表中心点值的基准进行选择。分割算法完成交换,从而使基准值在元素最终排序后被放置在列表中的正确位置上。
此时,下子列表只含有小于或等于基准值的元素,而上子列表只含有大于或等于基准值的元素。原始数组在递归下降之后变为有序数组。需要注意的是:归并排序对元素排序时还会将元素放置到临时数组中。而快速排序是通过在子列表之内交换元素对序列重新排序,所以快速排序是一种“原地置换(in-place)算法”。
三、示例代码
public class Quick { public static void QuickSort(int[] arr) { // call QSort QSort(arr, 0, arr.Length); } private static void QSort(int[] arr, int first, int last) { // index of the pivot int pivotLoc; // temp used for an exchange in a 2-elements list, int temp; // if the range is not at least two elements, return if (last - first <= 1) { return; } // if sublist has two elements, compares arr[first] and // arr[last-1] and exchange if necessary else if (last - first == 2) { if (arr[last - 1] < arr[first]) { temp = arr[last - 1]; arr[last - 1] = arr[first]; arr[first] = temp; } return; } else { pivotLoc = PivotIndex(arr, first, last); // make the recursive call QSort(arr, first, pivotLoc); // make the recursive call QSort(arr, pivotLoc + 1, last); } } private static int PivotIndex(int[] arr, int first, int last) { // index for the midpoint of [first,last] and // the indices that scan the index range in tandem int mid, scanUp, scanDown; // pivot value and array used for exchange int pivot, temp; // empty list if (first == last) { return last; } else if (first == last - 1) { // 1-elements sublist return first; } else { mid = (first + last) / 2; pivot = arr[mid]; // exchange the pivot and the low end of the range // and initialize the indices scanUp and scanDown scanUp = first + 1; scanDown = last - 1; // manage the indices to locate elements that are in // the wrong sublists; stop when scanDwon <= scanUp for (; ; ) { // move up the lower sublist; continue so long as // scanUp is less than or equal to scanDown and // the array value is less than pivot while (scanUp <= scanDown && arr[scanUp] < pivot) { scanUp++; } // move down the upper sublist so long as the array // value is greater than the pivot while (arr[scanDown] > pivot) { scanDown--; } // if indices are not in their sublists, partition complete if (scanUp >= scanDown) { break; } // indices are still in their sublists and identity // two elements in wrong sublists;exchanges temp = arr[scanUp]; arr[scanUp] = arr[scanDown]; arr[scanDown] = temp; scanUp++; scanDown--; } // copy pivot to index (scanDwon) that partitions // sublists and return scanDwon arr[first] = arr[scanDown]; arr[scanDown] = pivot; return scanDown; } } }
四、效率分析
不稳定。
空间复杂度:O(1)
时间复杂度:O(nlog2n)
最坏情况:O(n2),要排序数组基本有序,基准值每次取最大(最小)元素,退化为冒泡。
最好情况:O(nlog2n) 基准值两边元素个数基本相同.