算法基础之排序———快速排序(QuickSort)
我在大一时做的第一道排序题便是快速排序,当时刚学C语言,看了好久都没看懂,现在快一年过去了,我决定在这里分享下基础的快排算法,希望能帮助到看到这篇文章的同志们!
我们以int数组升序排序为例
-
算法概述
(1)对于一个数组,我们对其升序排序,则排序后的数组内每一个数的左侧永远小于它,右侧永远大于它,这里作为划分界限的“它”便可称为基准点。而我们要做的,便是把所有数都视为基准点来进行操作,当数组内的数全都可视为基准点了,数组也变有序了。
(2)对于每次循环,我们可以将第一个数当成基准点,我们要做的就是把比它小的数全部放在左边,其余放右边.我们可以设置一个左哨兵i和右哨兵j来实现,看完下面的例子你就懂啦! -
具体分析
对于如下数组a:
a[]:{5,3,6,8,4} (a[0]~a[4])
对于第一次循环:(1)我们先以5为基准,设置左哨兵i=0和右哨兵j=4,
(2)然后先从j开始往左找一个小于5的数或者 j 等于 i ,此时停下,j 指向 i 或者一个比5小的数,(这里必须 j 先进行查找,因为我们设置的基准点在第一个位置,到时候与基准交换的值必须小于基准值,先启动 j 的查找防止大值被交换至数组首位)
(3)然后从i开始往右找一个大于5的数或者 i 等于 j ,此时停下,i 指向一个比5大的数或者 i 等于 j(即指向比5小的数),此时若 i!=j,则交换i、j指向的数。
(4)这个时候如果 i 等于 j 了,说明此次循环已经比较完毕,对于基准值进行的数组遍历已经结束,就把基准值与a[i]互换,达到左小右大的结果。
全过程如下:
{5,3,(6),8,(4) } :i指向 6,j指向4,两者交换 {5,3,4,8,6}。 {5,3,(4),8,6}: i,j均指向4,交换5和4. {4,3,5,8,6}。 以{4,3}和{8,6}为新数组进行递归操作-->{3,4},{6,8} 最后数组即是{3,4,5,6,8}。
-
快排递归代码如下
void QuickSort(int left, int right, int a[])//升序
{
int i, j, temp, t;
if (left > right) return;
temp = a[left];//确认基准数
i = left;//确认左哨兵
j = right;//确认右哨兵
while (i != j) {
while (a[j] >= temp && j > i) j--;//从右往左找小数(j先查找)
while (a[i] <= temp && i < j) i++;//从左到右找大数
if (i < j) {//左右互换
t = a[i];
a[i] = a[j];
a[j] = t;
}
}
a[left] = a[i];//基准数归位
a[i] = temp;//基准数归位
//递归调用
QuickSort(left, i - 1, a);
QuickSort(i + 1, right, a);
return;
}
平均时间复杂度:O(n*logn)
(思路来源:啊哈算法)