快速排序(英语:Quicksort),又称划分交换排序(partition-exchange sort),简称快排,一种排序算法,最先由东尼·霍尔提出。在平均情况下,排序n个项目要O(nLogn)次比较。在最坏情况下则须要O(n^2)次比较,但这种情况并不常见。事实上,快速排序O(nLogn)一般明显比其余算法更快,由于它的内部循环(inner loop)能够在大部分的架构上颇有效率地达成
快速排序可能你们都学过,在面试中也常常会遇到,哪怕你是作前端的也须要会写,这里会列举两种不一样的快排代码进行分析前端
为了更深刻的理解,能够看下面这张图面试
咱们根据上面这张图,来用文字描述一下算法
以上就是快速排序基本的一个实现思想。segmentfault
这是我最近看到的一种快排代码数组
var quickSort = function(arr) { if (arr.length <= 1) { return arr; } var pivotIndex = Math.floor(arr.length / 2); var pivot = arr.splice(pivotIndex, 1)[0]; var left = []; var right = []; for (var i = 0; i < arr.length; i++) { if (arr[i] < pivot) { left.push(arr[i]); } else { right.push(arr[i]); } } return quickSort(left).concat([pivot], quickSort(right)); };
以上代码的实现方式是,选择一个中间的数字为基准点,用两个数组分别去保存比基准数小的值,和比基准数大的值,最后递归左边的数组和右边的数组,用concat去作一个数组的合并。数据结构
对于这段代码的分析:
缺点:架构
优势:ide
那么咱们接下来用另一种方式去实现快速排序函数
从上面这张图,咱们用一个指针i去作了一个分割oop
下面咱们来看一下代码的实现,整个代码分红三部分,数组交换,拆分,qsort(主函数)三个部分
先写最简单的数组交换吧,这个你们应该都懂
function swap(A, i ,j){ const t = A[i]; A[i] = A[j]; A[j] = t; }
下面是拆分的过程,其实就是对指针进行移动,找到最后指针所指向的位置
/** * * @param {*} A 数组 * @param {*} p 起始下标 * @param {*} r 结束下标 + 1 */ function dvide(A, p, r){ // 基准点 const pivot = A[r-1]; // i初始化是-1,也就是起始下标的前一个 let i = p - 1; // 循环 for(let j = p; j < r-1; j++){ // 若是比基准点小就i++,而后交换元素位置 if(A[j] <= pivot){ i++; swap(A, i, j); } } // 最后将基准点插入到i+1的位置 swap(A, i+1, r-1); // 返回最终指针i的位置 return i+1; }
主程序主要是经过递归去重复的调用进行拆分,一直拆分到只有一个数字。
/** * * @param {*} A 数组 * @param {*} p 起始下标 * @param {*} r 结束下标 + 1 */ function qsort(A, p, r){ r = r || A.length; if(p < r - 1){ const q = divide(A, p, r); qsort(A, p, q); qsort(A, q + 1, r); } return A; }
function swap(A, i, j) { const t = A[i]; A[i] = A[j]; A[j] = t; } /** * * @param {*} A 数组 * @param {*} p 起始下标 * @param {*} r 结束下标 + 1 */ function divide(A, p, r) { const x = A[r - 1]; let i = p - 1; for (let j = p; j < r - 1; j++) { if (A[j] <= x) { i++; swap(A, i, j); } } swap(A, i + 1, r - 1); return i + 1; } /** * * @param {*} A 数组 * @param {*} p 起始下标 * @param {*} r 结束下标 + 1 */ function qsort(A, p = 0, r) { r = r || A.length; if (p < r - 1) { const q = divide(A, p, r); qsort(A, p, q); qsort(A, q + 1, r); } return A; }
第二段的排序算法咱们减小了两个O(n)的操做,获得了必定的性能上的提高,而第一种方法数据规模足够大的状况下会相对来讲比较慢一些,快速排序在面试中也经常出现,为了笔试更好写一些可能会有更多的前端会选择第一种方式,但也会有一些为难人的面试官提出一些算法中的问题。而在实际的项目中,我以为第一种方式能够少用。
本人最近写的关于数据结构系列以下,欢迎你们看看点个赞哈:
js数据结构-栈
js数据结构-链表
js数据结构-队列
js数据结构-二叉树(二叉堆)
js数据结构-二叉树(二叉搜索树)