1秒记住快速排序!
Posted ACM算法日常
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了1秒记住快速排序!相关的知识,希望对你有一定的参考价值。
这几天在鼓捣算法动画视频,发现做动画比写算法题解有意思,因为每一行代码都能用动画显示出来,对于整个运行的流程更加直观,甚至能够看到大脑中没考虑到的细节。
上一篇文章我做了,这一篇还是做一个稍微简单点的动画:快速排序。
快速排序
快速排序在我印象里面比较不好记住,特别是以前看算法导论的时候,要花比较长的时间去理解逻辑,实现的时候还要考虑边界问题,容易做错。然而这一次制作动画视频的过程中,发现自己能够非常轻松的手写快速排序,于是才能总结出1秒记住快速排序的方法。下面让我们一起来看看快速排序吧。
快速排序时间复杂度是 ,最差情况下退化到 ,一般情况下还是很快的。算法基本结构是分治算法,如下代码:
void quick_sort(int arr[], int low, int high)
{
if (low < high) {
int anchor = partition(arr, low, high);
quick_sort(arr, low, anchor - 1);
quick_sort(arr, anchor + 1, high);
}
}
这段代码的意思是将区间[low, high]分成3部分,一个是锚点,一个是左区间,一个是右区间,对于左右区间,继续调用函数进行处理。每次调用都会把锚点位置空出来,像被镂空了一样。
这段代码没有记忆成本,只要能够理解肯定不需要死记硬背,所以记忆成本为0。
接下来看记忆成本为1秒的partition函数。
int partition(int arr[], int low, int high)
{
int anchor = arr[high];
int i = low - 1;
for (int j = low; j <= high - 1; j++) {
if (arr[j] <= anchor) {
// 永恒经典,一次遍历搞定绕着锚点分大小
swap(&arr[++i], &arr[j]);
}
}
// 最后把锚点放到中间来
swap(&arr[i + 1], &arr[high]);
//返回锚点的位置
return i + 1;
}
patition函数的作用可以单独来看,其功能是将一个区间分为3部分,锚点、左、右,如何在一次for循环中搞定这个事情呢?
首先是设定锚点,使用区间最右边的值作为锚点,然后遍历区间每一个数x,如果x小于锚点,就将x与左边的哨兵进行交换,因为x的位置肯定大于等于哨兵位置,所以交换不会产生副作用。最后将锚点交换到哨兵的下一个位置,完成分区任务。
一秒记忆
一句话记忆:将小于锚点的数放到左边
这句话和我们之前的一篇文章核心部分非常相似,也非常精巧,那就是,那个算法也是一句话记忆:将当前数与当前区间的一个数进行交换。
事实上,快速排序算法精巧的地方也在于一次for循环完成任务。如果你能理解Knuth随机算法的那一次for循环,那么理解快速排序甚至要简单一点。
大师的手段如出一辙。
动画解说
上面的代码用python原班实现,做成了如下动画:
总结
对于快速排序算法,核心部分其实只有两三行代码,可是在很久以前学习的时候却感觉很困难,而现在看又有一种简单的感觉,孔子说过温故而知新,也许就是这个道理。
以上是关于1秒记住快速排序!的主要内容,如果未能解决你的问题,请参考以下文章