前言 快速排序法在众多时间复杂度为N*logN的排序方法中效率极高,因此经常被使用。例如java中的Arrays.sort()还有python中的sort()都是采用优化过后的快速排序法。 要直接写出快速排序法并不简单,因此我写了这篇文章来谈谈对快速排序法的理解。
实现 快速排序是由C. A. R. Hoare在1962年提出的,是对冒泡排序法的一种改进。它的基本思想是: 1.从数组中取出一个数作为比较数。(一般为区间第一个数) 2.分区。将比这个数大的数放在它的右边,小于等于它的数放在左边。 3.再对左右两个分区进行第二步,知道各个分区只有一个数。 举个小数组的例子:
初始时,i=0,j=7,X=a[i]=67
由于X等于第一个数,相当于在a[0]上挖了一个坑,可以将其他位置的数填到这里。
接着从j开始向前找到一个比X小或相等的数。当j=6时,条件符合。将a[6]的值赋给a[0]。然后i++。这样又在a[6]上挖了一个坑。
之后再从i开始找到一个比X大的数,当i=5符合条件,将a[6]=a[5],j- -。
此时数组变为:
i=5,j=5,X=67;
如果i与j不相等,则重复上面的步骤,先从后往前找,再从前往后找。
当i==j时退出。然后将X的值填入下标i中。
此时可以发现,在a[5]之前的数都小于它,在a[5]之后的数都大于它。之后再对0--4和6--7两个子区间进行上述步骤即可。
# 代码
由此我们便可写出挖坑填数的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 int AdjustArray (int a[], int left, int right) { int i = left, j = right; int x = a[left]; while (i < j) { while (i < j && a[j] >= x) j--; if (i < j) { a[i] = a[j]; i++; } while (i < j && a[i] < x) i++; if (i < j) { a[j] = a[i]; j--; } } a[i] = x; return i; } void quick_sort (int a[], int left, int right) { if (left < right) { int i = AdjustArray(a, left, right); quick_sort(a, left, i - 1 ); quick_sort(a, i + 1 , right); } }
对代码优化之后即可得到简洁的快速排序法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 void quick_sort (int a[], int left, int right) { if (left < right) { int i = left, j = right, x = a[left]; while (i < j) { while (i < j && a[j] >= x) j--; if (i < j) a[i++] = a[j]; while (i < j && a[i] < x) i++; if (i < j) a[j--] = a[i]; } a[i] = x; quick_sort(a, left, i - 1 ); quick_sort(a, i + 1 , right); } }
快速排序法在理解上并不是很难,网上还有许多优化过的版本,这里不再细谈。