快速排序是找出一个元素(理论上可以随便找一个)作为基准(pivot),然后对数组进行分区操作,使基准左边元素的值都不大于基准值,基准右边的元素值都不小于基准值,如此作为基准的元素调整到排序后的正确位置。递归快速排序,将其他n-1个元素也调整到排序后的正确位置。先从右往左找一个小于基准的数,再从左往右找一个大于基准的数,然后交换他们。最后每个元素都是在排序后的正确位置,排序完成。所以快速排序算法的核心算法是分区操作,即如何调整基准的位置以及调整返回基准的最终位置以便分治递归。
- java
public class Quick {
public static void sort(Comparable[] a) {
StdRandom.shuffle(a);
show(a);
sort(a, 0, a.length - 1);
}
public static void sort(Comparable[] a, int lo, int hi) {
if (hi <= lo) {
return;
}
int j = partition(a, lo, hi);
sort(a, lo, j - 1);
sort(a, j + 1, hi);
}
private static int partition(Comparable[] a, int lo, int hi) {
int i = lo, j = hi + 1;
Comparable v = a[lo];
while (true) {
while (less(a[++i], v)) if (i == hi) break;
while (less(v, a[--j])) if (j == lo) break;
if (i >= j) break;
exch(a, i, j);
}
exch(a, lo, j);
return j;
}
public static boolean less(Comparable v, Comparable w) {
return v.compareTo(w) < 0;
}
public static void exch(Comparable[] a, int i, int j) {
Comparable t = a[i];
a[i] = a[j];
a[j] = t;
}
public static void show(Comparable[] a) {
for (int i = 0; i < a.length; i++) {
System.out.print(a[i] + " ");
}
System.out.println();
}
public static boolean isSorted(Comparable[] a) {
for (int i = 1; i < a.length; i++) {
if (less(a[i], a[i - 1])) {
return false;
}
}
return true;
}
public static void main(String[] args) {
String[] a = {"80", "30", "60", "40", "20", "10", "50", "70"};
sort(a);
assert isSorted(a);
show(a);
}
}
- python
import random
class Quick:
def quick_sort(self, data):
random.shuffle(data)
print(data)
self.do_sort(data, 0, len(data) - 1)
def do_sort(self, data, left, right):
if left >= right:
return
j = self.partition(data, left, right)
self.do_sort(data, left, j - 1)
self.do_sort(data, j + 1, right)
def partition(self, data, left, right):
v = data[left]
i = left + 1
j = right
while True:
while self.less(data[i], v):
if i == right:
break
i += 1
while self.less(v, data[j]):
if j == left:
break
j -= 1
if i >= j:
break
self.exch(data, i, j)
self.exch(data, left, j)
return j
def less(self, x, y):
return x < y
def exch(self, data, i, j):
data[i], data[j] = data[j], data[i]
if __name__ == "__main__":
s = [3, 4, 1, 6, 2, 9, 7, 0, 8, 5]
quick = Quick()
quick.quick_sort(s)
print(s)
快速排序和归并排序是互补的:归并排序将数组分成两个子数组分别排序,并将有序的子数组归并以将整个数组排序;而快速排序将数组排序的方式则是当两个子数组都有序时整个数组也就自然有序了。在归并排序中,一个数组被等分为两半;在快速排序中,切分的位置取决于数组的内容。
当数据量越来越大时,尽管归并排序的比较次数较少,但是归并排序后期的合并操作所花费的时间便越来越大,合并操作对整体的效率影响越来越明显,包括后面大量数据的赋值操作等。所以当数据量变大时,不需要专门合并的快速排序的优势就变得越发明显。