快速排序,从字面上讲就是快速的给数组排序的算法。想必大家最早学习的排序算法是冒泡排序,插入排序,选择排序等等,这些算法的时间复杂度都是o(n^2)的,效率较为低下。而本文要讲的快速排序算法可以在o(nlogn)的时间复杂度内给数组排序,在效率上实现了非常大的优化。
快速排序的思想
快速排序应用的是分治思想,对于原始数组,我们选定数组中的一个元素mid作为标准,利用双指针算法,遍历一遍数组进行调整,最终左右指针相遇的下标记为l,使得数组中满足下标小于l的元素的值都小于等于mid,下标大于l的所有元素的值都大于等于mid。
现在我们得到了两个新的数组,分别是l左侧的全部元素,l右侧的全部元素。我们只需要对这两个新的较小的数组分别排序,即可满足对原数组的排序了。
简单的来讲,总共有三步:
- 将数列划分为两部分(要求保证相对大小关系);
- 递归到两个子序列中分别进行快速排序;
- 不用合并,因为此时数列已经完全有序。
详细的视频示例可以参考下面的链接:https://www.bilibili.com/video/BV1j841197rQ/?spm_id_from=333.337.search-card.all.click&vd_source=f190a9af145747ca4566b4cae6a8ea36
快速排序的代码实现
注释:
由于需要排序的数组的元素类型是不定的,有时需要对int数组进行排序,有时需要对字符串按照字典序排序,或者给结构体数组排序,所以我们需要自己写一个比较函数check。check的返回值根据需要倒序还是正序自己决定。
快速排序的代码量还是非常非常少的,直接背过即可。
Datatype a[N];
void quick_sort(int l, int r)
{
int i = l - 1, j = r + 1;
Datatype mid = a[l + r >> 1]; //表示的是a[(l+r)/2],是笔者的习惯
do
{
while (check(a[++i], mid) >= 0);
while (check(a[--j], mid) <= 0);
if (i < j)
swap(a[i], a[j]);
} while (i < j);
quick_sort(l, j), quick_sort(j + 1, r);
}