js实现快速排序(in-place)简述
快速排序,又称划分交换排序。以分治法为策略实现的快速排序算法。
本文主要要谈的是利用javascript实现in-place思想的快速排序
分治法:
在计算机科学中,分治法是建基于多项分支递归的一种很重要的算法范式。字面上的解释是“分而治之”,就是把一个复杂的问题分成两个或更多的相同或相似的子问题,直到最后子问题可以简单的直接求解,原问题的解即子问题的解的合并。(摘自维基百科)
快速排序的思想
数组中指定一个元素作为标尺,比它大的放到该元素后面,比它小的放到该元素前面,如此重复直至全部正序排列。
快速排序分三步:
- 选基准:在数据结构中选择一个元素作为基准(pivot)
- 划分区:参照基准元素值的大小,划分无序区,所有小于基准元素的数据放入一个区间,所有大于基准元素的数据放入另一区间,分区操作结束后,基准元素所处的位置就是最终排序后它应该所处的位置
- 递归:对初次划分出来的两个无序区间,递归调用第 1步和第 2步的算法,直到所有无序区间都只剩下一个元素为止。
现在先说说普遍的实现方法(没有用到原地算法)
function quickSort(arr) {
if (arr.length <= 1) return ;
//取数组最接近中间的数位基准,奇数与偶数取值不同,但不印象,当然,你可以选取第一个,或者最后一个数为基准,这里不作过多描述
var pivotIndex = Math.floor(arr.length / 2);
var pivot = arr.splice(pivotIndex, 1)[0];
//左右区间,用于存放排序后的数
var left = [];
var right = [];
console.log('基准为:' + pivot + ' 时');
for (var i = 0; i < arr.length; i++) {
console.log('分区操作的第 ' + (i + 1) + ' 次循环:');
//小于基准,放于左区间,大于基准,放于右区间
if (arr[i] < pivot) {
left.push(arr[i]);
console.log('左边:' + (arr[i]))
} else {
right.push(arr[i]);
console.log('右边:' + (arr[i]))
}
}
//这里使用concat操作符,将左区间,基准,右区间拼接为一个新数组
//然后递归1,2步骤,直至所有无序区间都 只剩下一个元素 ,递归结束
return quickSort(left).concat([pivot], quickSort(right));
}
var arr = [14, 3, 15, 7, 2, 76, 11];
console.log(quickSort(arr));
/*
* 基准为7时,第一次分区得到左右两个子集[ 3, 2,] 7 [14, 15, 76, 11];
* 以基准为2,对左边的子集[3,2]进行划分区排序,得到[2] 3。左子集排序全部结束
* 以基准为76,对右边的子集进行划分区排序,得到[14, 15, 11] 76
* 此时对上面的[14, 15, 11]以基准为15再进行划分区排序, [14, 11] 15
* 此时对上面的[14, 11]以基准为11再进行划分区排序, 11 [14]
* 所有无序区间都只剩下一个元素,递归结束
*
*/
通过断点调试,可得出结果。
弊端:
它需要Ω(n)的额外存储空间,跟归并排序一样不好。在生产环境中,需要额外的内存空间,影响性能。
同时,很多人认为上边的就是真正的快速排序了。 所以,在下面,很有必要的推荐in-place算法的快速排序
有关于原地算法可参考维基百科,被墙的同学,百度也差不多。
in-place
快速排序一般是用递归实现,最关键是partition分割函数,它将数组划分为两部分,一部分小于pivot,另一部分大于pivot。具体原理上边提过
function quickSort(arr) {
// 交换
function swap(arr, a, b) {
var temp = arr[a];
arr[a] = arr[b];
arr[b] = temp;
}
// 分区
function partition(arr, left, right) {
/**
* 开始时不知最终pivot的存放位置,可以先将pivot交换到后面去
* 这里直接定义最右边的元素为基准
*/
var pivot = arr[right];
/**
* 存放小于pivot的元素时,是紧挨着上一元素的,否则空隙里存放的可能是大于pivot的元素,
* 故声明一个storeIndex变量,并初始化为left来依次紧挨着存放小于pivot的元素。
*/
var storeIndex = left;
for (var i = left; i < right; i++) {
if (arr[i] < pivot) {
/**
* 遍历数组,找到小于的pivot的元素,(大于pivot的元素会跳过)
* 将循环i次时得到的元素,通过swap交换放到storeIndex处,
* 并对storeIndex递增1,表示下一个可能要交换的位置
*/
swap(arr, storeIndex, i);
storeIndex++;
}
}
// 最后: 将pivot交换到storeIndex处,基准元素放置到最终正确位置上
swap(arr, right, storeIndex);
return storeIndex;
}
function sort(arr, left, right) {
if (left > right) return;
var storeIndex = partition(arr, left, right);
sort(arr, left, storeIndex - 1);
sort(arr, storeIndex + 1, right);
}
sort(arr, 0, arr.length - 1);
return arr;
}
console.log(quickSort([8, 4, 90, 8, 34, 67, 1, 26, 17]));
分区的优化
这里细心的同学可能会提出,选取不同的基准时,是否会有不同性能表现,答案是肯定的,但,因为,我是搞前端的,对算法不是很了解,所以,这个坑留给厉害的人来填补。
复杂度
快速排序是排序速度最快的算法,它的时间复杂度是O(log n)
在平均状况下,排序n个项目要Ο(n log n)次比较。在最坏状况下则需要Ο(n2)次比较.
js实现快速排序(in-place)简述的更多相关文章
- JS实现快速排序,冒泡排序
JS-排序详解-冒泡排序 说明 时间复杂度指的是一个算法执行所耗费的时间 空间复杂度指运行完一个程序所需内存的大小 稳定指,如果a=b,a在b的前面,排序后a仍然在b的前面 不稳定指,如果a=b, ...
- js算法-快速排序(Quicksort)
快速排序(英语:Quicksort),又称划分交换排序(partition-exchange sort),简称快排,一种排序算法,最早由东尼·霍尔提出.在平均状况下,排序n个项目要O(nLogn)次比 ...
- vue.js的一些模板指令简述
1.模板指令都是写在<template></template>html里面 v-text : value是什么就显示什么,如果value里面有html的标签,也会直接显示出 ...
- JS排序--快速排序
用 JavaScript 实现快速排序代码如下: /* * @author liphong * @data 2019/02/24 */ var arr = []; // 需要被排序数组 /* * 分离 ...
- 用JS实现快速排序
"快速排序"的思想很简单,整个排序过程只需要三步: (1)在数据集之中,选择一个元素作为"基准"(pivot). (2)所有小于"基准"的元 ...
- js数组快速排序/去重
数组的排序 快速排序 思路: (1)在数据集之中,选择一个元素作为”基准”(pivot). (2)所有小于”基准”的元素,都移到”基准”的左边:所有大于”基准”的元素,都移到”基准”的右边. (3) ...
- js数组快速排序和冒泡排序
1.快速排序 var arr = [1, 2, 5, 6, 3, 1, 4]; function mySort(arr) { if (arr.length <= 1) { return arr; ...
- js实现快速排序
非原创: var quickSort = function(arr){ if(arr.length<=1){return arr;} var pivotIndex = Math.floor(ar ...
- js数组快速排序
<script type="text/javascript"> var arr = [1, 2, 3, 54, 22, 1, 2, 3]; function quick ...
随机推荐
- LINQ to SQL更新数据库操作(转载)
使用LINQ to SQL建模Northwind数据库 在这之前一起学过LINQ to SQL设计器的使用,下面就使用如下的数据模型: 当使用LINQ to SQL设计器设计以上定义的五个类(Prod ...
- 【转】 浅谈Radius协议
浅谈Radius协议 2013-12-03 16:06 5791人阅读 评论(0) 收藏 举报 分类: Radius协议分析(6) 从事Radius协议开发有段时间了,小弟不怕才疏学浅,卖弄一下, ...
- 关于31天App教程示例中一些因SDK版本而出现的问题(转)
由于国外那个知名的31天案例教程比较老,所用官方API是2008年时的2.X,所以在现在的Xcode3-4之后或多或少都有编译警告和错误信息.必须做些适应iOS版本的代码更改才能顺利编译通过. Day ...
- linux下ping的C语言实现(转)
#include <stdio.h> #include <signal.h> #include <arpa/inet.h> #include <sys/typ ...
- excel插入当前时间快捷键Ctrl+;
之前写了一篇editplus如何插入当前时间_Ctrl+D的文章,有的同学说excel用习惯了,那在这我们就说一下excel插入当前时间快捷键,让您在excel快速插入当前时间 excel插入当前时间 ...
- [Effective JavaScript 笔记]第35条:使用闭包存储私有数据
js的对象系统并没有特别鼓励或强制信息隐藏.所有的属性名都是一个字符串,任意一个程序都可以简单地通过访问属性名来获取相应的对象属性.例如,for...in循环.ES5的Object.keys()和Ob ...
- JAVA经典算法40题及解答
JAVA经典算法40题 [程序1] 题目:古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第四个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少? 1.程序分 ...
- xcode arc引起的autorelease报错问题
http://blog.csdn.net/xiechengfa/article/details/37971223 自从用上了真苹果,一直升级,现在xcode版本是4.4,或者说是ios5 一直有个问题 ...
- [HDU5015]233 Matrix
[HDU5015]233 Matrix 试题描述 In our daily life we often use 233 to express our feelings. Actually, we ma ...
- Two Sum I & II
Two Sum I Given an array of integers, find two numbers such that they add up to a specific target nu ...