冒泡,快排算法之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 ...
随机推荐
- [Angular2 Router] Load Data Based on Angular 2 Route Params
You can load resource based on the url using the a combination of ActivatedRouteand Angular 2’s Http ...
- iOS开发——开发必备OC篇&UITableView设置界面完整封装(三)
UITableView设置界面完整封装(三) 简单MVC实现UITableView设置界面之界面跳转 创建一个需要调整的对应的控制器 在需要调整的类型模型中创建对应的属性用来实现调整类型控制器的设置 ...
- 剑指 offer set 1 二维数组中查找
总结 1. 二维数组搜索题遇到两个了, 一个是 Leetcode 上 search in 2D matrix. 那道题比较简单, 因为下一行的所有元素大于上一行的. 这道题对二维矩阵的要求比较松, 起 ...
- php常用代码(一)
一:获取上个小时 方法1:date("H",strtotime("-1 hours"); 方法2:date('H',time()-60*60); 方法3:ech ...
- c++ 设计模式5 (Observer / Event 观察者模式)
3.3 观察者模式 (Observer)/发布-订阅模式 动机: 在软件构建过程中,我们需要为某些对象建立一种“通知依赖关系”——一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都能得 ...
- 优化 App 的启动速度
App 的启动速度不仅影响我们调试,也直接关系到用户体验.之前有些很久没有打开过的项目,需要花费很长的时间才完成编译:对应的 App 在点击后,许久才出现启动画面.你是否为这些问题苦恼过呢? 这是我观 ...
- 升级树莓派archlinux系统到新sd卡
由于之前把树莓派系统安装在4gb的sd卡上,随着系统的更新及安装了一大堆软件包之后,系统提示空间不足了.网上搜索了下,把所有数据迁移到新的sd卡上还是比较简单的. 克隆sd卡: 1,关闭树莓派电源,取 ...
- [Java] HashMap遍历的两种方式
Java中HashMap遍历的两种方式原文地址: http://www.javaweb.cc/language/java/032291.shtml第一种: Map map = new HashMap( ...
- 纯CSS 多图片轮播
今天做东西的时候,遇到一个问题关于图片轮播的问题,以前也接触过(百度 人家的demo改改..),再次遇到这个问题的时候,根据以前的印象找到了demo正信心满满的准备改一下嵌进去,发现 jquery.m ...
- 用英文加优先级来解读C的声明
比如:int ( * func_p ) ( double ); 首先着眼于标识符. func_p is 因为存在括号,(* func_p) 先被处理,这里着眼于* func_p is a pointe ...