javascript 数组排序原理的简单理解
js内置的Array函数原型对象有个sort方法,这个方法能按照顺序排序数组。
例如:
var arr1 = [6, 4, 2, 5, 2];
arr1.sort((x, y) => x - y);
console.log(arr1); // [2, 2, 4, 5, 6];
以升序为例,这个方法的实现原理的简单理解:
第一轮比较。
先拿第一个数和第二个数字比较,如果第一个比第二个大,则交换位置。
接着又拿第一个数和第三个数比较,如果第一个比第三个大,则交换位置。
。。。
最后拿第一个数与最后一个数比较,如果第一个数比最后一个数大,则交换位置。
以上是第一轮比较。经过第一轮的比较。第一个数,就是数组中值最小的数了。
用上述例子来描述第一轮比较的过程,如图:

接着开始第二轮比较
先拿第二个数与第三个数比较,如果第二个比第三个大,则交换位置。
然后又拿第二个数和第四个数比较,如果第二个比第四个大,则交换位置。
。。。
最后拿第二个数与最后一个数比较,如果第二个数比最后一个数大,则交换位置。
以上是第二轮比较。经过第二轮的比较。第二个数,就是数组中值的第二小的数了。
用上述例子来描述第二轮比较的过程,如图:

循环往复直至全部都比较完。
上述例子的比较过程的代码演示:
function mySort(arr, cb) {
window.count = 0;// 统计循环次数
const res = cb && cb(1, 2);
let i, j, len = arr.length;
if (res < 0) {// 升序
for (i = 0; i < len; i++) {
for (j = i + 1; j < len; j++) {
count++;
if (arr[i] > arr[j]) {
[arr[i], arr[j]] = [arr[j], arr[i]];
}
}
}
} else {// 降序
for (i = 0; i < len; i++) {
for (j = i + 1; j < len; j++) {
count++;
if (arr[i] < arr[j]) {
[arr[i], arr[j]] = [arr[j], arr[i]];
}
}
}
}
}
这种排序方法循环次数为 (len - 1) * len / 2。
验证:
const arr = [];
for (let i = 0; i < 10; i++) {
arr.push(Math.floor(Math.random()*100));
}
mySort(arr, (x, y) => x - y);
结果:

采用排序二叉树结构的算法。代码演示:
function mySort(arr, cb) {
const res = cb && cb(1 ,2);
class Node {
constructor(key) {
this.key = key;
this.left = null;
this.right = null;
}
};
class BinaryTree {
constructor(key) {
this.root = null;
this.init(key);
}
init(key) {
this.root = new Node(key);
}
insert(key) {
const newNode = new Node(key);
this._insertNode(this.root, newNode);
}
_insertNode(root, node) {
if (node.key < root.key) {
if (!root.left) {
root.left = node;
} else {
this._insertNode(root.left, node);
}
} else {
if (!root.right) {
root.right = node;
} else {
this._insertNode(root.right, node);
}
}
}
inorderTraversal(callback) {
if (res < 0) {
this._inorderTraversalNodeSmall(this.root, callback);
} else {
this._inorderTraversalNodeBig(this.root, callback);
}
}
_inorderTraversalNodeSmall(node, callback) {
if (!!node) {
this._inorderTraversalNodeSmall(node.left, callback);
callback(node);
this._inorderTraversalNodeSmall(node.right, callback);
}
}
_inorderTraversalNodeBig(node, callback) {
if (!!node) {
this._inorderTraversalNodeBig(node.right, callback);
callback(node);
this._inorderTraversalNodeBig(node.left, callback);
}
}
}
const binaryTree = new BinaryTree(arr[0]);
let i, len;
for(i = 1, len = arr.length; i < len; i++) {
binaryTree.insert(arr[i]);
}
const _arr = [];
binaryTree.inorderTraversal(node => {
_arr.push(node.key);
});
return _arr;
}
测试:
const arr = [];
for (let i = 0; i < 10; i++) {
arr.push(Math.floor(Math.random()*100));
}
const newArr1 = mySort(arr, (x, y) => y - x);
const newArr2 = mySort(arr, (x, y) => x - y);
结果:

当数组比较大的时候,后面这种算法的优势明显。
现以后面这种算法为例,测试代码:
const arr = [];
for (let i = 0; i < 5000000; i++) {
arr.push(Math.floor(Math.random()*50000000));
}
const time = new Date().getMinutes() + ':' + new Date().getSeconds();
mySort(arr, (x, y) => x - y);
const nextTime = new Date().getMinutes() + ':' + new Date().getSeconds();
结果:

数组长度为5000000时,函数大概运行了6秒。
如果以第一种算法为例,5000000估计要好几分钟,这里缩减一下,设置成50000。测试代码:
const arr = [];
for (let i = 0; i < 50000; i++) {
arr.push(Math.floor(Math.random()*50000000));
}
const time = new Date().getMinutes() + ':' + new Date().getSeconds();
mySort(arr, (x, y) => x - y);
const nextTime = new Date().getMinutes() + ':' + new Date().getSeconds();
结果:

数组长度为50000时,函数大概运行了10秒。
第一种算法的耗时貌似也不是平滑增加的。估计也是一条陡峭的曲线。数学知识都忘光了。以后搞明白了在来完善。
javascript 数组排序原理的简单理解的更多相关文章
- mDNS 原理的简单理解
转自:http://www.binkery.com/post/318.html mDNS 原理的简单理解 mDNS multicast DNS , 使用5353端口. 在局域网内,你要通过一台主机和其 ...
- mDNS原理的简单理解——每个进入局域网的主机,如果开启了mDNS服务的话,都会向局域网内的所有主机组播一个消息,我是谁,和我的IP地址是多少。然后其他也有该服务的主机就会响应,也会告诉你,它是谁,它的IP地址是多少
MDNS协议介绍 mDNS multicast DNS , 使用5353端口,组播地址 224.0.0.251.在一个没有常规DNS服务器的小型网络内,可以使用mDNS来实现类似DNS的编程接口.包格 ...
- [转帖]mDNS原理的简单理解
mDNS原理的简单理解 https://binkery.com/archives/318.html 发现还有avahi-daemon mdns 设置ip地址 等等事项 网络部分 自己学习的还是不够多 ...
- How Javascript works (Javascript工作原理) (五) 深入理解 WebSockets 和带有 SSE 机制的HTTP/2 以及正确的使用姿势
个人总结: 1.长连接机制——分清Websocket,http2,SSE: 1)HTTP/2 引进了 Server Push 技术用来让服务器主动向客户端缓存发送数据.然而,它并不允许直接向客户端程序 ...
- HBase笔记:对HBase原理的简单理解
早些时候学习hadoop的技术,我一直对里面两项技术倍感困惑,一个是zookeeper,一个就是Hbase了.现在有机会专职做大数据相关的项目,终于看到了HBase实战的项目,也因此有机会搞懂Hbas ...
- 一些JavaScript中原理的简单实现
实现一个双向数据绑定 Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性, 并返回这个对象.通过这个属性可以实现简单的双向数据绑定,当前版 ...
- 【原创】分布式之数据库和缓存双写一致性方案解析(三) 前端面试送命题(二)-callback,promise,generator,async-await JS的进阶技巧 前端面试送命题(一)-JS三座大山 Nodejs的运行原理-科普篇 优化设计提高sql类数据库的性能 简单理解token机制
[原创]分布式之数据库和缓存双写一致性方案解析(三) 正文 博主本来觉得,<分布式之数据库和缓存双写一致性方案解析>,一文已经十分清晰.然而这一两天,有人在微信上私聊我,觉得应该要采用 ...
- 简单理解JavaScript闭包
很多关于JS的书籍例如<JavaScript权威指南>或者<高程>都把闭包解释的晦涩难懂,萌新们是怎么也看不懂啊!不过别怕,今天我就用很简单的方式给大家讲解下到底什么是闭包.这 ...
- 深入理解JavaScript Hijacking原理
最近在整理关于JavaScript代码安全方面的资料,在查关于JavaScript Hijacking的资料时,发现关于它的中文资料很少,故特意整理一下. 一.JavaScript Hijacking ...
随机推荐
- class文件格式版本号
major version 52:jdk 8, major version 51:jdk 7, major version 50:jdk 6, major version 49:jdk 5, majo ...
- android -------- SHA 加密算法
安全散列算法(英语:Secure Hash Algorithm,缩写为SHA)是一个密码散列函数家族,是FIPS所认证的安全散列算法.能计算出一个数字消息所对应到的,长度固定的字符串(又称消息摘要)的 ...
- ubuntu 18.04屏幕共享 -------(转载) ( Windows远程登录Ubuntu )
原文地址: https://my.oschina.net/michaelshu/blog/3018932 ----------------------------------------------- ...
- ISO/IEC 9899:2011 条款4——标准顺从
4. 标准顺从 1.在本国际标准中,“应该”被解释为对一个实现或一个程序的要求:相反地,“不该”被解释为禁用. 2.如果违反了出现在一个强制规定或运行时强制规定之外的“应该”或“不该”要求,那么该行为 ...
- cmake find_package说明
CMake中find_package功能演示 find_package可以被用来在系统中自动查找配置构建工程所需的程序库.在linux和unix类系统下这个命令尤其有用.CMake自带的模块文件里有大 ...
- Python代码编码规范
目录 1. Introduction 介绍 2. A Foolish Consistency is the Hobgoblin of Little Minds 尽信书,则不如无书 3. Code la ...
- Influx Sql系列教程三:measurement 表
在influxdb中measurement相当于mysql中的表,可以理解为一条一条记录都是存与measurent中的,一个数据库中可以有多个measurement,一个measurement中可以存 ...
- [转帖]【MySQL+keepalived】用keepalived实现MySQL主主模式的高可用
[MySQL+keepalived]用keepalived实现MySQL主主模式的高可用 https://www.jianshu.com/p/8694d07595bc 一.实验说明 MySQL主主模式 ...
- Linux学习-文件基础权限
文件基本权限 drwxr-xr-x 第一个字符表示文件类型 d:表示是一个目录.-:表示这是一个普通的文件.l: 表示这是一个符号链接文件,实际上它指向另一个文件.b.c:分别表示区块设备和其他的外围 ...
- Linux06 文件的打包和压缩(gzip/gunzip、tar、bzip2)
一.gzip/gunzip 这是用于压缩和解压单个文件的工具,且使用方法比较简单 gzip 文件名 gunzip 文件名 二.tar(用的比较多) 不仅可以用于打包文件,还可以将整个目录中的全部文 ...