为什么要写这篇文章
算法很难,又很难找到适合自己的理解方式,符合自己的前端算法入门教程难找
能学到什么
能自己说出来、写出来排序方法的原理,以及每一步写法的目的
如何阅读
先思考如何解决,5 分钟没思路,看文章解法,看完手写一遍,同时思考有没其他方法,第二天再次记忆。如果有基础,可回顾该算法原理、解法、时间空间复杂度、应用情景。
注:算法思想是一个意识积累的过程,看不懂不要着急,可以从原理、编程思想、动画演示、代码实现多个角度理解,如果还是理解不了,也不用灰心,先有个大体意识,后续积累到一定程度,自然融汇贯通
快速排序
1. 原理
先利用分治思想,将整个数组按照指定规则分成两个单元数组,再用递归思想,将得到的单元数组再次划分成两个,直到每一个单元数组只含有一个元素,然后拼接处理后的数组。
2. 实现步骤
在数组中随机选择一个值作为基准值,然后,将除了基准值以外的数分为“比基准值小的数”和“比基准值大的数”两个数组,递归(重复执行当前方法)划分,然后将划分好的数组拼接。
3. 动画示意
4. 代码实现
5. 代码实现分析
步骤一:选择一个基准值(根据个人心情,可以从数组中选择任意一个元素),此处选择 index 为 0 的第 1 个元素;
步骤二:定义两个空数组,left 存放比基准值小的数,right 存放比基准值大的数;
步骤三:在原数组中删除所选的基准值,由于这里选的是第一个元素,可以直接用 shift,如果你选的不是第一个,可用:oriArr.splice(index, 1)来删除,index 表示基准值在原数组中的下标索引。
步骤四:遍历数组,对除了基准值以外的元素进行分类,比基准值小的放到 left 数组,大于等于基准值的放到 right 数组;
步骤五:如果只执行一次,得到的 left 和 right 数组内元素依然是无序的,所以还要对 left 和 right 分别重复 sortQuick 方法做排序,这就是所谓的递归操作,最后把得到的结果拼接起来,当每一个单元数组只有一个元素时,就说明不能再拆分了,需要跳出循环,排序完成,这也就是为什么在函数一开始写了一个 return 的原因。
你可能还会看到使用 while 循环来实现的,没错,while 要实现的,就是条件循环。这里之所以这么写,是为了将步骤拆分开,看得更清楚。写完之后可以尝试试着用 while 条件循环再实现一次。
6. 快速排序小结:
快速排序利用了分治思想(无限二分)再递归排序的思想,将一个整体的数组排序问题分为两个子问题的排序问题,而解决子问题的排序时又使用到了快速排序,像这样在算法内部使用该算法的现象就称为“递归”。
由于每一次划分都会将原数组划分为两分数组,因此总共会划分出 log2n(log以2为底,n的对数) 个数组;每一个单元数组中的每一个数字都需要和基准值比较大小,因此一个单元数组会和基准值比较次数为n,所以,整体的平均运行时间就为:O(nlogn)