JS 这一次彻底理解冒泡排序
壹 ❀ 引
在面试环节中,算法总是逃不掉的一关,对于我这种非班科出生且大学不接触数学的人来说,逻辑思维方面确实较为欠缺,昨晚跟百度的同学聊到凌晨,自我感觉差距较大,受了不小打击,所以决心抓一抓算法,做做相关训练题,我可能没天赋,但做一点总比什么都不做要强,这篇文章从十大排序中的冒泡排序说起。
贰 ❀ 冒泡排序基本概念
在水中,空气的密度比水轻,所以水中的气泡会不断上浮,这是我们生活中所理解的冒泡。而冒泡排序的概念也是如此。
对于一个数组,我们会比较相邻的两个元素,如果前者比后者大,则需要交换两者的位置,也就是较大的后沉,较小的往前浮,看个最简单的例子。

let arr = [2, 1];
//比较索引0,与索引1的两个元素,如果前者比后者大,交换两者位置。
if (arr[0] > arr[1]) {
//交换位置
arr[0] = [arr[1], arr[1] = arr[0]][0]
};
arr; //[1,2]
当然,这个例子特别简单,因为只包含2个元素,所以我们只需要遍历一次,且只比较一次即可得到最终排序结果。
我们将数组升级,再加一项:
let arr = [3,2,1];
此时只比较一次很明显解决不了问题,不过数量不多,我们尝试拆分比较过程。
- 第一次遍历
- 第一次比较
- 3比2大,交换位置,得到数组
[2,3,1];
- 3比2大,交换位置,得到数组
- 第二次比较
- 3比1大,再次交换位置,得到数组
[2,1,3];
- 3比1大,再次交换位置,得到数组
- 第一次比较
此时第一次遍历结束,我们发现目前数组并没有排序完成,还需要再遍历一次:
- 第二次遍历
- 第一次比较
- 2比1大,交换位置,得到数组
[1,2,3];
- 2比1大,交换位置,得到数组
- 第一次比较
此时排序完成,为什么第二次只需要比较一次呢?这是因为第一次遍历一定会将数组当前最大项移到数组尾部,所以第二次比较没有意义。
为了论证这一点,我们将数组再次升级,再多加一项,拆分步骤如下:
let arr = [4,2,3,1];
- 第一次遍历
- 第一次比较
- 4比2大,交换位置,得到数组
[2,4,3,1];
- 4比2大,交换位置,得到数组
- 第二次比较
- 4比3大,交换位置,得到数组
[2,3,4,1];
- 4比3大,交换位置,得到数组
- 第三次比较
- 4比1大,交换位置,得到数组
[2,3,1,4],此时第一次遍历结束,看来还需要再次遍历。
- 4比1大,交换位置,得到数组
- 第一次比较
- 第二次遍历
- 第一次比较
- 2比3小,不需要交换位置,数组维持不变
[2,3,1,4];
- 2比3小,不需要交换位置,数组维持不变
- 第二次比较
- 3比1大,交换位置,得到数组
[2,1,3,4];
- 3比1大,交换位置,得到数组
- 第一次比较
你看,我们又不需要进行第三次比较,因为第一次遍历已经将最大的4移动到了数组末尾,所以第三次比较毫无意义。由于数组还没排序完毕,我们需要进行第三次遍历:
- 第三次遍历
- 第一次比较
- 2比1大,交换位置,得到数组[1,2,3,4];
- 第一次比较
此时我们已经得到了最终排序,所以不需要进行第二次比较与第三次比较。
细心的同学可能已经发现了一个规律,针对同一个数组,每遍历一次,都会将当前最大的元素移动到数组末尾,且下次遍历的比较次数需要相比上次少一次。
再说的直白点,还是上面的例子,第1遍历需要比较3次,确定了当前最大数4。第二次遍历只需要比较2次,确定了当前最大数3,第三次遍历只需要比较1次,确定了当前最大数2。
我们综合上诉三个例子来做个总结:
- 数组有2项时,需要遍历1次,比较1次。
- 数组有3项时,需要遍历2次,第一次比较2次,第二次比较1次。
- 数组有4项时,需要遍历3次,第一次比较3次,第二次比较2次,第三次比较1次。
我们好像得到了一个结论,当数组有N项时,需要遍历N-1次,且每次遍历的比较次数为N - 当前遍历次数(也就是i+1,因为是从i=0开始,所以加个1)。
所以我们可以用2个for循环,外层用于定义遍历次数,内层用于定义比较次数。
叁 ❀ 冒泡排序实现
知道了这个规律,我们直接上代码:
let arr = [3, 1, 5, 4, 7, 6, 0, 2];
function bubbleSort(arr) {
var length = arr.length,
i = 0;
// 遍历次数为length-1次
for (; i < length - 1; i++) {
// 当前遍历的比较次数为length - 当前遍历次数
for (var j = 0; j < length - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
arr[j] = [arr[j + 1], arr[j + 1] = arr[j]][0];
};
};
};
return arr;
};
bubbleSort(arr); //[0, 1, 2, 3, 4, 5, 6, 7]
百度百科给的代码示例外层使用了while循环,思路一样,代码如下:
function bubbleSort(arr) {
var i = arr.length, j;
var tempExchangVal;
while (i > 0) {
for (j = 0; j < i - 1; j++) {
if (arr[j] > arr[j + 1]) {
tempExchangVal = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tempExchangVal;
};
};
i--;
};
return arr;
};
var arr = [3, 2, 4, 9, 1, 5, 7, 6, 8];
但是这段代码有个问题,前面我们知道当数组有N项,就需要遍历N-1次,很明显这段代码中使用while(i>0)会无意义的多执行一次,这里改成while(i>1)会好一点。
那么关于数组冒泡排序就说到这里,本人笨拙,为了解释清楚冒泡的过程,只能采取找规律来加深理解,若文中有描述不当之处,还望指出,那么到这里本文结束。
肆 ❀ 参考
JS 这一次彻底理解冒泡排序的更多相关文章
- 封装常用的js(Base.js)——【01】理解库,获取节点,连缀,
封装常用的js(Base.js)——[01]理解库,获取节点,连缀, youjobit07 2014-10-10 15:32:59 前言: 现如今有太多优秀的开源javascript库, ...
- 关于js with语句的一些理解
关于js with语句的一些理解 今天看到js的with语句部分,书中写到,with语句接收的对象会添加到作用域链的前端并在代码执行完之后移除.看到这里,我有两点疑问,添加到作用域链前端是不是指对 ...
- [ 转载 ] js十大排序算法:冒泡排序
js十大排序算法:冒泡排序 http://www.cnblogs.com/beli/p/6297741.html
- JS高阶函数的理解(函数作为参数传递)
JS高阶函数的理解 高阶函数是指至少满足下列条件之一的函数. · 函数可以作为参数被传递 · 函数可以作为返回值输出 一个例子,我们想在页面中创建100个div节点,这是一种写法.我们发现并不是所有用 ...
- 使用 js 实现十大排序算法: 冒泡排序
使用 js 实现十大排序算法: 冒泡排序 冒泡排序 refs xgqfrms 2012-2020 www.cnblogs.com 发布文章使用:只允许注册用户才可以访问!
- 图说js中的this——深入理解javascript中this指针
没搞错吧!js写了那么多年,this还是会搞错!没搞错,javascript就是回搞错! ………… 文章来源自——周陆军的个人网站:http://zhoulujun.cn/zhoulujun/html ...
- 《深入浅出Node.js》第6章 理解 Buffer
@by Ruth92(转载请注明出处) 第6章 理解 Buffer ✁ 为什么需要 Buffer? 在 Node 中,应用需要处理网络协议.操作数据库.处理图片.接收上传文件等,在网络流和文件的操作中 ...
- Node.js的process.nextTick(callback)理解
Node.js是单线程的,基于事件循环,非阻塞 IO的.事件循环中使用一个事件队列,在每个时间点上,系统只会处理一个事件,即使电脑有多个CPU核心,也无法同时并行的处理多个事件.因此,node.js适 ...
- Js 职责链模式 简单理解
js 职责链模式 的简单理解.大叔的代码太高深了,不好理解. function Handler(s) { this.successor = s || null; this.handle = funct ...
- JS魔法堂:彻底理解0.1 + 0.2 === 0.30000000000000004的背后
Brief 一天有个朋友问我“JS中计算0.7 * 180怎么会等于125.99999999998,坑也太多了吧!”那时我猜测是二进制表示数值时发生round-off error所导致,但并不清楚具体 ...
随机推荐
- 第65篇 AJAX初识 校验用户名 登录示例 文件上传 csrftoken
1, 知识储备 2. AJAX的定义 异步的JavaScript和XML 使用场景: JavaScript和后端的数据传递 2.1原生的JavaScript实现AJAX 2.2 JQuery实现 2. ...
- 1. 在Windows10上使用dbca配置oracle19.3.0.0时,报错DBT-50000 无法检查可用内存。
1.如图所示,在安装过程中,我遇到了错误提示,无法检查可用内存,导致安装失败. 在咨询后,认为是内存不足导致的问题,便清理了内存,重新安装.但是依旧出现以上内容,检查自己的内存大小,远远大于其安装所需 ...
- CSS - 使用CSS 3D属性来完成页面视差滚动效果。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- [转帖]Web技术(七):如何使用并实现MQTT 消息订阅-发布模型?
文章目录 一.什么是发布-订阅消息模型? 二.订阅-发布消息模型有哪些应用? 2.1 应用于IP 物联网络中的消息传递 2.2 应用于操作系统进程间的消息传递 2.3 应用于MESH 自组网中的消息传 ...
- [转帖]jmap执行失败了,怎么获取heapdump?
https://www.jianshu.com/p/f4bfd169b4ca 在之前的OOM问题复盘中,我们添加了jmap脚本来自动dump内存现场,方便排查OOM问题. 但当我反复模拟OOM场景 ...
- [转帖]SQL标准
SQL 的标准 1986 年 10 月,美国国家标准协会 ANSI 采用 SQL 作为关系数据库管理系统的标准语言,并命名为 ANSI X3. 135-1986,后来国际标准化组织(ISO)也采纳 S ...
- Widows 关闭 Defender的方法
Study From MS reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows Defender" /v ...
- 【团队效率提升】Python-PyWebIO介绍
作者:京东零售 关键 Q&A快速了解PyWebIO Q:首先,什么是PyWebIO? A:PyWebIO提供了一系列命令式的交互函数,能够让咱们用只用Python就可以编写 Web 应用, 不 ...
- RN 动态渲染列表
写在组件中 想要图片出来还应该给图片宽高哈!! alignItems: 'center', //水平居中 动态渲染列表 返回的是一个数组 网络图片的渲染方式 <Image source={{ur ...
- 【分享一个工具】通过定义proto3来自动生成多进程模式的插件代码
作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢! cnblogs博客 zhihu Github 公众号:一本正经的瞎扯 我在多进程插件框架 hashicorp/go-plugin ...