js内置的Array函数原型对象有个sort方法,这个方法能按照顺序排序数组。

例如:

  1. var arr1 = [6, 4, 2, 5, 2];
  2. arr1.sort((x, y) => x - y);
  3. console.log(arr1); // [2, 2, 4, 5, 6];

以升序为例,这个方法的实现原理的简单理解:

第一轮比较。

先拿第一个数和第二个数字比较,如果第一个比第二个大,则交换位置。

接着又拿第一个数和第三个数比较,如果第一个比第三个大,则交换位置。

。。。

最后拿第一个数与最后一个数比较,如果第一个数比最后一个数大,则交换位置。

以上是第一轮比较。经过第一轮的比较。第一个数,就是数组中值最小的数了。

用上述例子来描述第一轮比较的过程,如图:

接着开始第二轮比较

先拿第二个数与第三个数比较,如果第二个比第三个大,则交换位置。

然后又拿第二个数和第四个数比较,如果第二个比第四个大,则交换位置。

。。。

最后拿第二个数与最后一个数比较,如果第二个数比最后一个数大,则交换位置。

以上是第二轮比较。经过第二轮的比较。第二个数,就是数组中值的第二小的数了。

用上述例子来描述第二轮比较的过程,如图:

循环往复直至全部都比较完。

上述例子的比较过程的代码演示:

  1. function mySort(arr, cb) {
  2. window.count = 0;// 统计循环次数
  3. const res = cb && cb(1, 2);
  4. let i, j, len = arr.length;
  5. if (res < 0) {// 升序
  6. for (i = 0; i < len; i++) {
  7. for (j = i + 1; j < len; j++) {
  8. count++;
  9. if (arr[i] > arr[j]) {
  10. [arr[i], arr[j]] = [arr[j], arr[i]];
  11. }
  12. }
  13. }
  14. } else {// 降序
  15. for (i = 0; i < len; i++) {
  16. for (j = i + 1; j < len; j++) {
  17. count++;
  18. if (arr[i] < arr[j]) {
  19. [arr[i], arr[j]] = [arr[j], arr[i]];
  20. }
  21. }
  22. }
  23. }
  24. }

这种排序方法循环次数为 (len - 1) * len / 2。

验证:

  1. const arr = [];
  2. for (let i = 0; i < 10; i++) {
  3. arr.push(Math.floor(Math.random()*100));
  4. }
  5. mySort(arr, (x, y) => x - y);

结果:

采用排序二叉树结构的算法。代码演示:

  1. function mySort(arr, cb) {
  2. const res = cb && cb(1 ,2);
  3. class Node {
  4. constructor(key) {
  5. this.key = key;
  6. this.left = null;
  7. this.right = null;
  8. }
  9. };
  10. class BinaryTree {
  11. constructor(key) {
  12. this.root = null;
  13. this.init(key);
  14. }
  15. init(key) {
  16. this.root = new Node(key);
  17. }
  18. insert(key) {
  19. const newNode = new Node(key);
  20. this._insertNode(this.root, newNode);
  21. }
  22. _insertNode(root, node) {
  23. if (node.key < root.key) {
  24. if (!root.left) {
  25. root.left = node;
  26. } else {
  27. this._insertNode(root.left, node);
  28. }
  29. } else {
  30. if (!root.right) {
  31. root.right = node;
  32. } else {
  33. this._insertNode(root.right, node);
  34. }
  35. }
  36. }
  37. inorderTraversal(callback) {
  38. if (res < 0) {
  39. this._inorderTraversalNodeSmall(this.root, callback);
  40. } else {
  41. this._inorderTraversalNodeBig(this.root, callback);
  42. }
  43. }
  44. _inorderTraversalNodeSmall(node, callback) {
  45. if (!!node) {
  46. this._inorderTraversalNodeSmall(node.left, callback);
  47. callback(node);
  48. this._inorderTraversalNodeSmall(node.right, callback);
  49. }
  50. }
  51. _inorderTraversalNodeBig(node, callback) {
  52. if (!!node) {
  53. this._inorderTraversalNodeBig(node.right, callback);
  54. callback(node);
  55. this._inorderTraversalNodeBig(node.left, callback);
  56. }
  57. }
  58. }
  59.  
  60. const binaryTree = new BinaryTree(arr[0]);
  61. let i, len;
  62. for(i = 1, len = arr.length; i < len; i++) {
  63. binaryTree.insert(arr[i]);
  64. }
  65. const _arr = [];
  66. binaryTree.inorderTraversal(node => {
  67. _arr.push(node.key);
  68. });
  69. return _arr;
  70. }

测试:

  1. const arr = [];
  2. for (let i = 0; i < 10; i++) {
  3. arr.push(Math.floor(Math.random()*100));
  4. }
  5. const newArr1 = mySort(arr, (x, y) => y - x);
  6. const newArr2 = mySort(arr, (x, y) => x - y);

结果:

当数组比较大的时候,后面这种算法的优势明显。

现以后面这种算法为例,测试代码:

  1. const arr = [];
  2. for (let i = 0; i < 5000000; i++) {
  3. arr.push(Math.floor(Math.random()*50000000));
  4. }
  5. const time = new Date().getMinutes() + ':' + new Date().getSeconds();
  6. mySort(arr, (x, y) => x - y);
  7. const nextTime = new Date().getMinutes() + ':' + new Date().getSeconds();

结果:

数组长度为5000000时,函数大概运行了6秒。

如果以第一种算法为例,5000000估计要好几分钟,这里缩减一下,设置成50000。测试代码:

  1. const arr = [];
  2. for (let i = 0; i < 50000; i++) {
  3. arr.push(Math.floor(Math.random()*50000000));
  4. }
  5. const time = new Date().getMinutes() + ':' + new Date().getSeconds();
  6. mySort(arr, (x, y) => x - y);
  7. const nextTime = new Date().getMinutes() + ':' + new Date().getSeconds();

结果:

数组长度为50000时,函数大概运行了10秒。

第一种算法的耗时貌似也不是平滑增加的。估计也是一条陡峭的曲线。数学知识都忘光了。以后搞明白了在来完善。

二叉树的实现原理的简单理解

javascript 数组排序原理的简单理解的更多相关文章

  1. mDNS 原理的简单理解

    转自:http://www.binkery.com/post/318.html mDNS 原理的简单理解 mDNS multicast DNS , 使用5353端口. 在局域网内,你要通过一台主机和其 ...

  2. mDNS原理的简单理解——每个进入局域网的主机,如果开启了mDNS服务的话,都会向局域网内的所有主机组播一个消息,我是谁,和我的IP地址是多少。然后其他也有该服务的主机就会响应,也会告诉你,它是谁,它的IP地址是多少

    MDNS协议介绍 mDNS multicast DNS , 使用5353端口,组播地址 224.0.0.251.在一个没有常规DNS服务器的小型网络内,可以使用mDNS来实现类似DNS的编程接口.包格 ...

  3. [转帖]mDNS原理的简单理解

    mDNS原理的简单理解 https://binkery.com/archives/318.html 发现还有avahi-daemon mdns 设置ip地址 等等事项 网络部分 自己学习的还是不够多 ...

  4. How Javascript works (Javascript工作原理) (五) 深入理解 WebSockets 和带有 SSE 机制的HTTP/2 以及正确的使用姿势

    个人总结: 1.长连接机制——分清Websocket,http2,SSE: 1)HTTP/2 引进了 Server Push 技术用来让服务器主动向客户端缓存发送数据.然而,它并不允许直接向客户端程序 ...

  5. HBase笔记:对HBase原理的简单理解

    早些时候学习hadoop的技术,我一直对里面两项技术倍感困惑,一个是zookeeper,一个就是Hbase了.现在有机会专职做大数据相关的项目,终于看到了HBase实战的项目,也因此有机会搞懂Hbas ...

  6. 一些JavaScript中原理的简单实现

    实现一个双向数据绑定 Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性, 并返回这个对象.通过这个属性可以实现简单的双向数据绑定,当前版 ...

  7. 【原创】分布式之数据库和缓存双写一致性方案解析(三) 前端面试送命题(二)-callback,promise,generator,async-await JS的进阶技巧 前端面试送命题(一)-JS三座大山 Nodejs的运行原理-科普篇 优化设计提高sql类数据库的性能 简单理解token机制

    [原创]分布式之数据库和缓存双写一致性方案解析(三)   正文 博主本来觉得,<分布式之数据库和缓存双写一致性方案解析>,一文已经十分清晰.然而这一两天,有人在微信上私聊我,觉得应该要采用 ...

  8. 简单理解JavaScript闭包

    很多关于JS的书籍例如<JavaScript权威指南>或者<高程>都把闭包解释的晦涩难懂,萌新们是怎么也看不懂啊!不过别怕,今天我就用很简单的方式给大家讲解下到底什么是闭包.这 ...

  9. 深入理解JavaScript Hijacking原理

    最近在整理关于JavaScript代码安全方面的资料,在查关于JavaScript Hijacking的资料时,发现关于它的中文资料很少,故特意整理一下. 一.JavaScript Hijacking ...

随机推荐

  1. Netty 读写检测机制(心跳)

    一.创建服务端 1.MyServer 类 public class MyServer { public static void main(String[] args) throws Exception ...

  2. python练习:寒冰猴子狐狸,猫狗咬架

    python练习:寒冰猴子狐狸,猫狗咬架 一,寒冰猴子狐狸 class Person: def __init__(self, na, gen, age, fig): self.name = na se ...

  3. vue---自定义指令的使用

    在vue开发项目中,指令的使用场景也是比较多的,那么该如何定义使用呢? 找到 src / directive 下新建 gender 目录,下面新建 index.js 和 gender.js index ...

  4. 十三、postman导出java代码

    导出成java的OkHttp代码 使用Junit进行接口自动化测试 使用fastJSON解析json字符串 创建个实体类 package com.netease.AcFunTest; public c ...

  5. 必须要注意的 C++ 动态内存资源管理(二)——指针对象简单实现

    必须要注意的 C++动态内存资源管理(二)——指针对象简单实现 四.拷贝类型的资源         上节我们说过,对于图片类型的资源我们有时候往往采用拷贝(如果对于那种公共图片,可能采用唯一副本,提供 ...

  6. pytorch保证每次运行使用的随机数都相同的方法

    其实在代码的开头添加下面几句话即可: # 保证训练时获取的随机数都是一样的 init_seed = torch.manual_seed(init_seed) torch.cuda.manual_see ...

  7. 本机安装了oracle,本机还需要安装客户端吗?

    转: 本机安装了oracle,本机还需要安装客户端吗? 2017-09-21 15:56:29 Ideality_hunter 阅读数 4681   版权声明:本文为博主原创文章,遵循CC 4.0 B ...

  8. 【Tools】HP/惠普v285w 量产工具

    前段时间朋友说自己u盘坏了,让帮忙看看.看下图是这个u盘. 坏的问题:往里面复制东西,提示:请去掉写保护或使用另一张磁盘.但是能正常从里面读取出来数据. 无论更换电脑,还是使用网上的修改注册表等方式皆 ...

  9. PHP命令行参数

    原文地址:http://php.swoole.com/wiki/PHP%E5%91%BD%E4%BB%A4%E8%A1%8C%E5%8F%82%E6%95%B0   PHP命令行参数 目录 [隐藏]  ...

  10. Delphi 将视频 Base64 字符串转换为视频二进制文件

    var Bytes: TBytes; Stream: TBytesStream; begin with System.NetEncoding.TBase64Encoding.Create do try ...