原文出自:

http://www.nczonline.net/blog/2012/11/27/computer-science-in-javascript-quicksort/

https://gist.github.com/paullewis/1981455#file-gistfile1-js

快速排序(Quicksort)是对冒泡排序的一种改进,是一种分而治之算法归并排序的风格

核心的思想就是通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列

理论上的步骤:

  1. 找到一个“支点”项目在数组中,可以是中心点,基准
  2. 在阵列中的第一项开始指针(左指针)。
  3. 在数组中的最后一个项目开始一个指针(右指针)。
  4. 而在左指针数组中的值小于枢轴值,将左指针向右(加1)。 继续,直到在左指针的值大于或等于所述枢轴值。
  5. 而在合适的指针数组中的值大于枢轴值,将右指针向左(减去1)。 继续下去,直到在正确的指针的值小于或等于所述枢轴值。
  6. 如果左指针是小于或等于右指针,然后交换的值在数组中的这些位置。
  7. 移动左指针向右由1和右指针向左之一。
  8. 如果左指针和右指针不符合,请转到步骤1。

原文太罗嗦了,简单的来说

  1. 在数据集之中,选择一个元素作为"基准"(pivot)。
  2. 所有小于"基准"的元素,都移到"基准"的左边;所有大于"基准"的元素,都移到"基准"的右边。
  3. 对"基准"左边和右边的两个子集,不断重复第一步和第二步,直到所有子集只剩下一个元素为止。

来个实际的demo

var items = [4, 2, 6, 5, 3, 9];

具体的流程算法如下:

针对这一组数组,如何选择这个支点呢,有些算法选择第一项为支点, 这是不是最好的选择,性能最差。 一般更好地选择数组中间的支点,所以考虑5是枢轴值(数组的长度除以2)

接下来从左边拿0位置拿第一个数与支点5对比,如果4<5,那么指针的位置就偏移到1,然后2<5,一次类推

如果6>5的时候,此时左边的指针就停止移动

然后从右边的指针开始移动,也是如此,只是右边是取的大于的值,比如9>5 ,往前移位,3<5,此时也停止移动,然后交换指针对应的数值


第一步:选择支点

第二步: 指针在前后开始偏移

第三步:如果4<5,继续移动左边的指针往下

第四步:如果2<5,往下,6>5停止

第五步:9>5,往前,3<5停止

第六步:交换指针指向的值

第七步:继续如上的操作,直到支点

第八部:如果指针到了支点,就停止


配合实现交换的swap的代码

function swap(items, firstIndex, secondIndex){
var temp = items[firstIndex];
items[firstIndex] = items[secondIndex];
items[secondIndex] = temp;
}

实现的代码

function partition(items, left, right) {
var pivot = items[Math.floor((right + left) / 2)],
i = left,
j = right;
while (i <= j) {
while (items[i] < pivot) {
i++;
}
while (items[j] > pivot) {
j--;
}
if (i <= j) {
swap(items, i, j);
i++;
j--;
}
}
return i;
}

这个函数接受三个参数: items ,这是值进行排序的阵列, left ,这是该指数以启动左指针时,和right ,这是该指数以启动右指针。 枢轴值是通过将所确定的leftright的值,然后除以2。 因为这个值可能是一个浮点数,有必要进行一些舍入。

整个算法是循环只是一个循环。 外环确定何时所有的数组范围的项目已经被处理。 左,右指针的两个内部循环控制运动。当两个内部循环的完成,则该指针进行比较,以确定是否交换是必要的。 在交换之后,两个指针被移动,使外循环继续,在合适的地方。 该函数返回的左指针的值,因为这是用于确定从哪里开始隔间的下一次。 请记住,该分区是发生在地方,而不会产生任何额外的数组。

快速排序算法基本上通过划分整个阵列的工作原理,然后递归地分割阵列的左侧和右侧的部分,直到整个阵列被排序。

在前面的例子中,数组变[4, 2, 3, 5, 6, 9]一个分区,并返回索引后为4(左指针的最后一个席位),开始递归左右2个分割阵列

如下面的图所示

第一步:找到指针遍历的位置,确定支点

第二步:从左右指针位置开始,对比4<3,停止

第三步:因为5>3,移动右边的指针,因为3==3,停止

第四步:交换指针指向的值

第五步:依次如上处理

第六步:因为2<3,移动左边指针,因为4>3,停止

因为左边的指针超过了右边的指针,停止

该过程之后,该阵列变成[3, 2, 4, 5, 6, 9]和返回的索引是1,继续这样,直到所有的阵列左侧的排序。 然后相同的处理接着在右侧的阵列。 基本对数的快速排序,然后变得非常简单:

function quickSort(items, left, right) {
var index;
if (items.length > 1) {
index = partition(items, left, right);
if (left < index - 1) {
quickSort(items, left, index - 1);
}
if (index < right) {
quickSort(items, index, right);
} }
return items;
} // first call
var result = quickSort(items, 0, items.length - 1);

快速排序通常被认为是高效,快速等特点是使用V8引擎的实现Array.prototype.sort()上有超过23个项目的数组。 对于少于23个项目,V8采用插入排序法[2]。

归并排序是快速排序的竞争对手,因为它也是高效,快捷,但有被稳定的好处。 这就是为什么Mozilla和Safari中使用它自己的执行Array.prototype.sort()

Javascript算法系列之快速排序(Quicksort)的更多相关文章

  1. 算法实例-C#-快速排序-QuickSort

    算法实例 ##排序算法Sort## ### 快速排序QuickSort ### bing搜索结果 http://www.bing.com/knows/search?q=%E5%BF%AB%E9%80% ...

  2. 排序算法四:快速排序(Quicksort)

    快速排序(Quicksort),因其排序之快而得名,虽然Ta的平均时间复杂度也是O(nlgn),但是从后续仿真结果看,TA要比归并排序和堆排序都要快. 快速排序也用到了分治思想. (一)算法实现 pr ...

  3. 排序算法系列:快速排序算法JAVA版(靠谱、清晰、真实、可用、不罗嗦版)

    在网上搜索算法的博客,发现一个比较悲剧的现象非常普遍: 原理讲不清,混乱 啰嗦 图和文对不上 不可用,甚至代码还出错 为了不误人子弟耽误时间,推荐看一些靠谱的资源,如[啊哈!算法]系列: https: ...

  4. 小小c#算法题 - 6 - 快速排序 (QuickSort)

    快速排序是排序算法中效率比较高的一种,也是面试常被问到的问题. 快速排序(Quick Sort)是对冒泡排序的一种改进.它的基本思想是,通过一趟排序将待排记录分割成独立的两部分,其中一部分记录的关键字 ...

  5. 【JavaScript数据结构系列】00-开篇

    [JavaScript数据结构系列]00-开篇 码路工人 CoderMonkey 转载请注明作者与出处 ## 0. 开篇[JavaScript数据结构与算法] 大的计划,写以下两部分: 1[JavaS ...

  6. JAVA算法系列 快速排序

    java算法系列之排序 手写快排 首先说一下什么是快排,比冒泡效率要高,快排的基本思路是首先找到一个基准元素,比如数组中最左边的那个位置,作为基准元素key,之后在最左边和最右边设立两个哨兵,i 和 ...

  7. javascript实现数据结构与算法系列:栈 -- 顺序存储表示和链式表示及示例

    栈(Stack)是限定仅在表尾进行插入或删除操作的线性表.表尾为栈顶(top),表头为栈底(bottom),不含元素的空表为空栈. 栈又称为后进先出(last in first out)的线性表. 堆 ...

  8. 快速排序(quicksort)算法实现

    快速排序(quicksort)是分治法的典型例子,它的主要思想是将一个待排序的数组以数组的某一个元素X为轴,使这个轴的左侧元素都比X大,而右侧元素都比X小(从大到小排序).然后以这个X在变换后数组的位 ...

  9. 排序系列 之 快速排序算法 —— Java实现

    基本思想: 通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变 ...

随机推荐

  1. 数据泵Expdp和Impdp

    一.数据泵导入导出技术 1.结构 2.目录对象 二.EXPDP参数 1.attach 2.content 3.directory 4.dumpfile 5.estimate 6.estimate_on ...

  2. 使用IHTMLDocument2解决弹出"为了让该网站给你提供个人化信息,是否允许在你计算机放置cookie?"

    mshtml可以说是一个不错的解析html利器,对于像我这样一直都是不用webbrowser,直接用socket或者WebRequest进行HTTP通讯 然后再用IHTMLDocument2.writ ...

  3. 可变字符串NSMutableString

    //可变字符串继承自字符串 //拼接 NSMutableString *string = [NSMutableString string]; [string appendString:@"今 ...

  4. HDU---BigZhuGod的粉丝

    Problem Description 真正的粉丝,是不需要题目描述的^_^.   Input 第一行输入数据组数T(1≤T≤100).接下来T行,每行一个有格式的字符串,详见样例,字符串长度不超过1 ...

  5. hdfs 复制路径下所有文件

    hadoop fs -cp $SRC_FILE $TARGET_FILE hadoop fs -cp $SRC_DIR $TARGET_DIR 注:复制路径时,最后一个斜杠是没有的.添加斜杠后报文件找 ...

  6. 代码编辑器Sublime Text 3 免费使用方法与简体中文汉化包下载

    Sublime Text这款代码编辑器是Jeff 一直都在使用的,前段时间转用到版本3,因为感觉Sublime Text 3 启动速度更加快,运行更加流畅——虽然3 还是在Beta 阶段.下面就直接分 ...

  7. 电容参数:X5R,X7R,Y5V,COG 详解

    电容参数:X5R,X7R,Y5V,COG 详解 文章来源:http://www.hzlitai.com.cn/article/ARM9-article/cphard/1777.html 仅供分享学习~ ...

  8. Kafka使用入门教程

    转载自http://www.linuxidc.com/Linux/2014-07/104470.htm 介绍 Kafka是一个分布式的.可分区的.可复制的消息系统.它提供了普通消息系统的功能,但具有自 ...

  9. mysql添加一个用户

    对于添加mysql的远程访问用户,一定要记得刷新刷新系统权限表不然你怎么弄都是不成功的. insert into mysql.user(Host,User,Password) values(" ...

  10. 数据库中数据DELETE了怎样恢复

    USE [BBDAS_FP_DATA] GO /****** Object: StoredProcedure [dbo].[Recover_Deleted_Data_Proc] Script Date ...