快速排序离不开递归的思想,你若是不了解递归,能够结合我另一篇文章来学习 算法入门之递归分而治之思想的实现javascript
网上有有趣的动态图来表示快速排序,但其实咱们大部分程序员都是脑子不太好使那种,即便看了形象生动的动态图,仍是想不到具体实现思路。java
排序都有基本的步骤,快排也不例外,一般分为这么几步:程序员
一、选择基准值;算法
二、须要2个空数组,分别位于基准值的左边和右边,小于基准值的push到左边的数组,大于基准值的push到右边的数组;segmentfault
三、递归重复上面的步骤。数组
原始数组 | [2, 4, 1, 5, 3, 1] |
---|---|
找基准值 base | 末尾元素1 |
拆分 | left [1] <- [base] -> [2, 4, 5, 3] right |
递归 | 对left和right的数组重复第一步找新的基准值 |
模拟递归1 | [1], [1], [2] <- [3] -> [4, 5] |
模拟递归2 | [1], [1], [2], [3], [4] <- [5] -> [] |
递归结束,合并数组 | [...[1], ...[1], ...[2], ...[3], ...[4], ...[5]] |
这个表格模拟快速排序的具体步骤,递归是将一种规律重复执行N次的操做,咱们找到快速排序的规律,而后return 递归,当递归到数组为1个元素时,再也不递归,由于只剩一个元素的数组不须要再比较了。函数
理论理解起来很容易,但常常是实际写代码,无从下手,下面是我根据快排的步骤实现的递归快速排序。qSort函数不复杂,他表示执行一次找基准值而且遍历比较的过程,而你可能不太理解的是函数最后面的return。学习
return [...qSort(left), ...[base], ...qSort(right)]
将这个return拆分开来看。code
一、返回值应该是个数组 。排序
return []
二、合并第一次快速排序的left,base,right数组。接着就交给递归去执行左边和右边数组的排序。
return [qSort(left), [base], qSort(right)]
三、由于qSort返回的是数组,不是数组元素,因此须要用ES6语法...来散列开。
完整代码:
function qSort(arr) { //声明并初始化左边的数组和右边的数组 var left = [], right = [] //使用数组最后一个元素做为基准值 var base = arr[arr.length - 1] //当数组长度只有1或者为空时,直接返回数组,不须要排序 if(arr.length <= 1) return arr //进行遍历 for(var i = 0, len = arr.length; i < len - 1; i++) { if(arr[i] <= base) { //若是小于基准值,push到左边的数组 left.push(arr[i]) } else { //若是大于基准值,push到右边的数组 right.push(arr[i]) } } //递归而且合并数组元素 return [...qSort(left), ...[base], ...qSort(right)] } const arr = [2, 4, 1, 5, 3, 1] const s = qSort(arr) console.log(s) // [1, 1, 2, 3, 4, 5]
快速排序的平均时间复杂度是O(nlogn),最差状况是O(n²)。