冒泡,快排算法之javascript初体验
引子:javascript实际使用的排序算法在标准中没有定义,可能是冒泡或快排。不用数组原生的 sort() 方法来实现冒泡和快排。
Part 1:冒泡排序(Bubble Sort)
- 原理:临近的两数两两进行比较,按从小到大或从大到小顺序排列,进行多趟,每一趟过去后(外循环),最大或最小的数字被交换到最后一位(内循环)。
- 代码:共进行6趟,每一趟比较5次
var a=[6,2,4,1,5,9],t;
for(var i=0;i<a.length;i++){
for(var j=0;j<a.length-1;j++){
if(a[j]>a[j+1]){
t=a[j];
a[j]=a[j+1];
a[j+1]=t;
}
}
}
-----分割线----更正于2016.2.25
更正冒泡代码:
- 代码:共进行5趟(最后一趟即要开始比较的最后一个数不用比较了,它已经被其他趟挤到该在的位置了),每一趟比较5-i次,因为那i次在上一趟中已经排好序了在该在的位置了,肯定是前小后大没什么可比较的了,即后面继续比较无意义。
var a=[6,2,4,1,5,9],t;
for(var i=0;i<a.length-1;i++){
for(var j=0;j<a.length-1-i;j++){
if(a[j]>a[j+1]){
t=a[j];i
a[j]=a[j+1];
a[j+1]=t;
}
}
}
Part 2:快速排序(Quick Sort)
- 原理:在一个个数为n的序列中找一个数作为基准数(任意哪个皆可,一般找第一个),即找到该基准数所在位置k,k作为分界点,k左边数均小于基准数,k右边数均大于基准数。
- 具体做法:设置i,j两个指针分别指向最左端和最右端,每次比较都从j指针开始向左移动寻找比基准数小的数后停止移动,然后指针i向右移动寻找比基准数大的数后停止移动,交换此时i,j所指向的内容,这算一趟中的一次交换完成,直到i,j指针相遇位置即找到k,将基准数和k位置的数字交换,这算完成一趟排序。(解释一下为什么每次一定要从j指针移动开始:举个栗子说明,某序列为[3,1,2,5,4],基准数为3,i指向3,j指向4,如你所愿假设先从i移动找比3大的,i指针移动到5停止,j指针找比3小的,移动到5时相遇了,所以5的位置即为k,交换3和5,序列变为[5,1,2,3,4],这显然越排越乱。之所以一定要从右边开始就是保证了从右边过滤的是比基准数小的,然后再从左边移动时即使相遇了也能保证这个数比基准数小交换后不会影响序列)
- 分析原理:用分治的思想进行多趟寻找,每一趟都找出基准数所在位置,其中每一趟最坏情况都是两个指针指向了相邻元素,进行交换,这样比较次数和交换次数和冒泡一样了。所以快排在最坏情况下时间复杂度和冒泡一样O(n2)。但快排的平均时间复杂度为O(nlogn),快排之所以比冒泡有优势,在于每次交换都是跳跃式的,不一定每个位置都交换,而且每一趟序列的个数有可能是大于1那样的递减因为k位置不确定划分后才能确定左右两边序列个数,但冒泡每一趟比较序列的个数是规律的每次少一个(n,n-1,n-2...),快排不是像冒泡相邻交换,跳跃式的交换使交换距离变大,因此总的比较和交换次数变少,速度自然就提高。
- 举例:某序列[6,1,2,7,9,3, 4,5,10,8],说明以下图片均引用自网络(侵删)
以6作为基准数,寻找分界点k。
1.现在i,j指针均已就位

2.j指针先从右往左找小于6的数再停下,然后i指针再从左往右找大于6的数再停下,最后交换

3.第一趟的第一次交换完毕,序列变为[6,1,2,5,9,3,4,7,10,8]

4.j指针继续向左寻找小于6的元素,i指针继续向右寻找大于6的元素,最后交换

5.第一趟的第二次交换完毕,序列变为[6,1,2,5,4,3,9,7,10,8]

6.j指针继续向左寻找小于6的元素,i指针继续向右寻找大于6的元素,到3时相遇停止移动,即找到位置k

7.交换3和6,第一趟排序完毕。序列变为[3,1,2,5,4,6,9,7,10,8]


8.剩下的就每一趟都是按此方式重排,可用分治的思想解决,先解决6左边的序列,完毕后再解决6右边序列,直到不可拆分出新的子序列为止

- 代码:为了测试代码差点把浏览器搞崩,一不小心少了某个条件就进入死递归了。。。
function quicksort(a,left,right){
if(left>right){ //一定要有这个判断,因为有递归left和i-1,若没有这个判断条件,该函数会进入无限死错位递归
return;
} var i=left,
j=right,
jizhun=a[left]; //基准总是取序列开头的元素 while(i!=j){ //该while的功能为每一趟进行的多次比较和交换最终找到位置k。当i==j时意味着找到k位置了
while(a[j]>=jizhun&&i<j){j--} //只要大于等于基准数,j指针向左移动直到小于基准数才不进入该while。i<j的限制条件也是很重要,不然一直在i!=j这个循环里,j也会越界
while(a[i]<=jizhun&&i<j){i++} //只要小于等于基准数,i指针向右移动直到大于基准数才不进入该while。等于条件也是必要的,举例[4,7,6,4,3]验证一下是两个4交换
if(i<j){ //如果i==j跳出外层while
t=a[i];
a[i]=a[j];
a[j]=t
}
} a[left]=a[i];//交换基准数和k位置上的数
a[i]=jizhun; quicksort(a,left,i-1);
quicksort(a,i+1,right);
} var array=[4,7,2,8,3,9,12];
quicksort(array,0,array.length-1);//排完序后再看array是[2, 3, 4, 7, 8, 9, 12]
性能测试:在jsperf整了个链接测试一下冒泡,快排,sort()对100个数字排序的性能,http://jsperf.com/sortdemo 果然还是sort()原生方法快。
在chrome控制台统计代码执行的时间,也同样验证了sort()原生方法快:



参考:http://developer.51cto.com/art/201403/430986.htm
冒泡,快排算法之javascript初体验的更多相关文章
- 快排算法Java版-每次以最左边的值为基准值手写QuickSort
如题 手写一份快排算法. 注意, 两边双向找值的时候, 先从最右边起找严格小于基准值的值,再从最左边查找严格大于基准base的值; 并且先右后左的顺序不能反!!这个bug改了好久,233~ https ...
- 【算法】桶排->冒泡->快排
啊哈 算法 http://pan.baidu.com/s/1jGGl2SI http://pan.baidu.com/s/15C1oq 1 节 最快最简单的排序——桶排序 在我们生活的这个世界中到处都 ...
- Java写 插入 选择 冒泡 快排
/** * Created by wushuang on 2014/11/19. */ public class SortTest { @Test public void mainTest() { i ...
- python快排算法
通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列. ...
- 快排算法(C++版)
#include <iostream> using namespace std; /** Quick Sort * * split: cmp && swap * left ...
- oc 快排算法
直接复制粘贴就可以用了 - (void)viewDidLoad { [super viewDidLoad]; NSMutableArray *M_arr = [[NSMutableArray allo ...
- javascript初体验(一)
数据类型 数字 (Number),整数或浮点数,例如42或3.14159 字符串 (String) 布尔值 (Boolean) null (js大小写敏感,因此null和NULL不一样) undefi ...
- 快排 - 快速排序算法 (Chinar出品 简单易懂)
Quicksort 快排的简单讲解 本文提供全流程,中文翻译. Chinar 坚持将简单的生活方式,带给世人!(拥有更好的阅读体验 -- 高分辨率用户请根据需求调整网页缩放比例) Chinar -- ...
- scala写算法-快排
快排算法很经典,今天用scala的函数式思维来整理一下并实现: def qsort(list: List[Int]):List[Int]=list match { case Nil=>Nil c ...
随机推荐
- Mysql之EXPLAIN显示using filesort
索引使用经验: 1. 一条 SQL 语句只能使用 1 个索引 (5.0-),MySQL 根据表的状态,选择一个它认为最好的索引用于优化查询 2. 联合索引,只能按从左到右的顺序依次使用 Using w ...
- alljoyn连接时-fno-rtti选项测试结果
以AllJoyn自带的chat示例在pc上测试结果如下: libAllJoyn.a编译选项 Chat编译选项 测试结果 -Wall -Werror=non-virtual-dtor -pipe -st ...
- c++ 设计模式6 (Decorator 装饰模式)
4. “单一职责”类模式 在软件组件的设计中,如果责任划分的不清晰,使用继承得到的结果往往是随着需求的变化,子类急剧膨胀,同时充斥着重复代码,这时候的关键是划清责任. 典型模式代表: Decorato ...
- JS后退, JS返回上一页, JS返回下一页
Javascript 返回上一页: 1. history.go(-1), 返回两个页面: history.go(-2); 2. history.back(). 3. window.history.fo ...
- 1.7.4.3 Parsers
Parsers 除了主查询解析器外,还有一些其他的查询解析器可以使用或者和主查询解析器连合使用.这部分描述了其他查询解析器的细节,并且给出了一些例子: 大多数的解析器都可以使用局部查询参数的方式来表达 ...
- JSF HelloWord
JSF(Java Server Faces)是一种用于构建Web应用程序的新标准Java框架.提供了一种以组件为中心来开发Java Web的用户界面的方法,从而简化了开发. JSF是Java We ...
- Linux重定向的理解
/* 重定向的实例 dup2函数 利用filefd来代替STDOUT(标准输出流),write写入filefd的数据,重定向写出到STDOUT中: */ #include <stdio.h> ...
- javaScript入门2--变量,作用域,内存
变量类型:基本类型和引用类型 基本类型上节已经提到.基本类型的值是按值传递的,既改变形参的值不会影响实参 <html> <head> <meta charset=&quo ...
- (转)Linux IO模式及 select、poll、epoll详解
本文为转载,并作了部门调整.修改. [原文出处:https://segmentfault.com/a/1190000003063859] 同步IO和异步IO,阻塞IO和非阻塞IO分别是什么,到底有什么 ...
- java处理高并发高负载类网站的优化方法
java处理高并发高负载类网站中数据库的设计方法(java教程,java处理大量数据,java高负载数据) 一:高并发高负载类网站关注点之数据库 没错,首先是数据库,这是大多数应用所面临的首个SPOF ...