JavaScript实现in-place思想的快速排序方法_javascript技巧

快速排序,又称划分交换排序。以分治法为策略实现的快速排序算法。

本文主要要谈的是利用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)次比较.

https://github.com/LYZ0106/

以上所述是小编给大家介绍的JavaScript实现in-place思想的快速排序方法,希望对大家有所帮助,如果大家有任何疑问欢迎给我留言,小编会及时回复大家的,在此也非常感谢大家对网站的支持!

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索js快速排序
javascript冒泡排序、javascript 排序、javascript 数组排序、javascript排序算法、javascript快速排序,以便于您获取更多的相关知识。

时间: 2025-01-21 16:50:06

JavaScript实现in-place思想的快速排序方法_javascript技巧的相关文章

javascript先序遍历DOM树的方法_javascript技巧

DOM树由文档中的所有节点(元素节点.文本节点.注释节点等)所构成的一个树结构,DOM树的解析和构建是浏览器要实现的关键功能.既然DOM树是一个树结构,那么我们就可以使用遍历树结构的相关方法来对DOM树进行遍历,同时DOM2中的"Traversal"模块又提供了两种新的类型,从而可以很方便地实现DOM树的先序遍历. 注:本文中的5种方法都是对DOM的先序遍历方法(深度优先遍历),并且只关注Element类型. 1. 使用DOM1中的基础接口,递归遍历DOM树 DOM1中为基础类型Nod

JavaScript通过字符串调用函数的实现方法_javascript技巧

本文实例讲述了JavaScript通过字符串调用函数的实现方法.分享给大家供大家参考.具体分析如下: JavaScript中我们可以把根据函数名的字符串来调用函数,这样我们就可以实现动态函数调用,只需要传递一个函数的名字即可调用该函数. 复制代码 代码如下: var strFun = "someFunction"; //Name of the function to be called var strParam = "this is the parameter";

javascript中的后退和刷新实现方法_javascript技巧

<input type=button value=刷新 onclick="window.location.reload()"> <input type=button value=前进 onclick="window.history.Go(1)"> <input type=button value=后退 onclick="window.history.go(-1)"> <input type=button

JavaScript动态检验密码强度的实现方法_javascript技巧

平时我们会在某些网站的注册页面或者更改密码的页面发现当我们输入密码时,会有一个类似于进度条的长条进行提示用户输入的密码强度.如下图: 我看到有些人用几张不同的图片来替换,这样似乎可以,但是不太好.所以我通过其他方式实现. 实质上这是根据用户输入的不同密码强度来改变 颜色区域的长度. 密码强度这个横条实质是一个div,其他标记也可以,div里面有一个span标记,我就是通过改变span的长度和颜色来表现密码的强度的.原理很简单,但是在操作过程中,可能会遇到一些问题很头疼. 1.先在html页面里面

JavaScript实现通过select标签跳转网页的方法_javascript技巧

本文实例讲述了JavaScript实现通过select标签跳转网页的方法.分享给大家供大家参考,具体如下: 我们经常有遇到需要用select标签跳转到新网页的情况,dw生成的代码太复杂,那么有没有精简的代码得以实现呢?经过仔细的研究找到了以下几段代码,非常不错. 话不多说,直奔主题. 当面跳转的核心代码是:"location.href=value" 新页面打开的核心代码是:"window.open()" 代码分四类: 1.当前页面直接跳转: <select n

使用JavaScript获取Request中参数的值方法_javascript技巧

假设现在有一个URL,如下. http://www.jb51.net 如何通过JS访问到id和name里面的值呢,实现我们来分析一下思路. 先获取当前页面的URL,通过window.location.href. 提取该URL?后面的部分,通过slice()方法. 把获取到的Request对象分割成字符串数组,通过split() 方法. 接下来看代码. function getUrlVars() { var vars = [], hash; var hashes = window.location

javascript浏览器窗口之间传递数据的方法_javascript技巧

本文实例讲述了javascript浏览器窗口之间传递数据的方法.分享给大家供大家参考.具体分析如下: 摘要: 在项目开发中我们经常会遇到弹窗,有的是通过div模拟弹窗效果,有的是通过iframe,也有通过window自带的open函数打开一个新的窗口.今天给大家分享的是最后一种通过window.open()函数打开页面进行数据交互.首先看下效果图: 原理: 父窗口给子窗口传递数据是通过url的参数传递过去,子窗口给父窗口传递数据是通过父窗口的全局函数传递. 代码:index.html如下: 复制

javascript实现状态栏中文字动态显示的方法_javascript技巧

本文实例讲述了javascript实现状态栏中文字动态显示的方法.分享给大家供大家参考,具体如下: <script> var child = window.open("information.html","_blank","width=200,height=200,toolbar=no"); function closeChild(){ if(!child.closed){ child.close(); } } //设置间隔1秒钟,调

JavaScript实现获取dom中class的方法_javascript技巧

本文实例讲述了JavaScript实现获取dom中class的方法.分享给大家供大家参考.具体实现方法如下: <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title></title> <script> function getClass(node,classname) { if(node.getEle