排序算法 JavaScript

一、冒泡排序

算法介绍:

1.比较相邻的两个元素,如果前一个比后一个大,则交换位置。

2.第一轮把最大的元素放到了最后面。

3.由于每次排序最后一个都是最大的,所以之后按照步骤1排序最后一个元素不用比较。

function bubble_sort(arr){var swap;  for(var i=0;i<arr.length-1;i++){for(var j=0;j<arr.length-i-1;j++){if(arr[j]>arr[j+1]){swap=arr[j];arr[j]=arr[j+1];arr[j+1]=swap;}}}
}

冒泡算法改进:
1.设置一个标志,如果这一趟发生了交换,则为true。否则为false。如果这一趟没有发生交换,则说明排序已经完成。代码如下:

function bubble_sort_1(arr) {var n = arr.length,flag = true,swap;while(flag){flag = false;for(var j = 1; j<n; j++){if(arr[j - 1]>arr[j]) {swap = arr[j-1];arr[j-1] = arr[j];arr[j] = swap;flag = true;}0}n --;  }return arr;
}

2.假如数组长度是20,如果只有前十位是无序排列的,后十位是有序且都大于前十位,所以第一趟遍历排序的时候发生交换的位置必定小于10,且该位置之后的必定有序,我们只需要排序好该位置之前的就可以,因此我们要来标记这个位置就可以了,即可以记录每次扫描中最后一次交换的位置,下次扫描的时候只要扫描到上次的最后交换位置就行了,因为后面的都是已经排好序的,无需再比较,代码如下:

function bubble_sort_2(arr) {var n=arr.length;var j,k;  var flag=n;var swap;while(flag>0) {  k=flag;  flag=0;  for(j=1;j<k;j++){ if (arr[j - 1] > arr[j])  {  swap=arr[j-1];arr[j-1]=arr[j];arr[j]=swap;flag=j;  }  }  } }

 3.每一次循环从两头出发算出最大和最小值,代码如下:

function bubble_sort_3(arr) {var low = 0;var high= arr.length-1; //设置变量的初始值var swap,j;while (low < high) {for (j= low; j< high; ++j) {         //正向冒泡,找到最大者if (arr[j]> arr[j+1]) {swap = arr[j]; arr[j]=arr[j+1];arr[j+1]=swap;}}--high;  //修改high值, 前移一位for (j=high; j>low; --j) {          //反向冒泡,找到最小者if (arr[j]<arr[j-1]) {swap = arr[j]; arr[j]=arr[j-1];arr[j-1]=swap;}} ++low;  //修改low值,后移一位
  }return arr;
}

4.在代码3的基础上记录每次扫描最后一次交换的位置,下次扫描的时候只要扫描到上次的最后交换位置就行,同代码2,代码如下:

function bubble_sort_3(arr) {var low = 0;var high= arr.length-1; //设置变量的初始值var swap,j;while (low < high) {var pos1 = 0,pos2=0; for (let i= low; i< high; ++i) { //正向冒泡,找到最大者if (arr[i]> arr[i+1]) {swap = arr[i]; arr[i]=arr[i+1];arr[i+1]=swap;pos1 = i ;}}high = pos1;// 记录上次位置for (let j=high; j>low; --j) { //反向冒泡,找到最小者if (arr[j]<arr[j-1]) {swap = arr[j]; arr[j]=arr[j-1];arr[j-1]=swap;  pos2 = j;}}   low = pos2; //修改low值
  }return arr;
}

 冒泡排序动图演示:

二、快速排序

算法介绍:

快速排序是对冒泡排序的一种改进,第一趟排序时将数据分成两部分,一部分比另一部分的所有数据都要小。然后递归调用,在两边都实行快速排序。

function quick_sort(arr){if(arr.length<=1){return arr;}var pivotIndex=Math.floor(arr.length/2);var pivot=arr.splice(pivotIndex,1)[0];var left=[];var right=[];for(var i=0;i<arr.length;i++){if(arr[i]<pivot){left.push(arr[i]);}else{right.push(arr[i]);}}return quick_sort(left).concat([pivot],quick_sort(right));
}

快速排序动图演示:

 

 

三、选择排序

算法介绍:

选择排序就是从一个未知数据空间里,选取之最放到一个新的空间,代码如下:

function selection_sort(arr) {var len = arr.length;var minIndex, swap;for (var i = 0; i < len - 1; i++) {minIndex = i;for (var j = i + 1; j < len; j++) {if (arr[j] < arr[minIndex]) { //寻找最小的数minIndex = j; //将最小数的索引保存
      }}swap = arr[i];arr[i] = arr[minIndex];arr[minIndex] = swap;}return arr;
}

选择排序动图演示:

 

四、插入排序

算法介绍:

 1.从第一个默认被排好序的元素开始

2.取出下一个元素,在已经排序的元素序列中从后向前扫描

3.如果已排序的元素大于取出的元素,则将其分别向后移动一位

4.直到找到已排序的元素中小于或等于取出的元素,将取出的元素放到它的后一位

5.重复步骤2

代码如下:

function insertion_sort(arr) {for (var i = 1; i < arr.length; i++) {var key = arr[i];var j = i - 1;while ( arr[j] > key) {arr[j + 1] = arr[j];j--;}arr[j + 1] = key;}return arr;
}

插入排序算法改进-二分法插入排序:

function binaryInsertion_sort(arr) {for (var i = 1; i < arr.length; i++) {var key = arr[i], left = 0, right = i - 1;while (left <= right) {var middle = parseInt((left + right) / 2);if (key < arr[middle]) {right = middle - 1;} else {left = middle + 1;}}for (var j = i - 1; j >= left; j--) {arr[j + 1] = arr[j];}arr[left] = key;}return arr;
}

插入排序法动图演示:

 

五、希尔排序

算法介绍:

希尔排序是冒泡排序的一种更高效率的实现。它与冒泡排序的不同之处在于,它会优先比较距离较远的元素。希尔排序的核心在于间隔序列的设定。

上图中先每差5为一组进行比较,之后再每差2为一组惊醒比较,最后就是两两比较。代码如下:

function shell_sort(arr) {var len = arr.length,temp,gap = 1;while(gap < len/5) { //动态定义间隔序列gap =gap*5+1;}for (gap; gap > 0; gap = Math.floor(gap/5)) {for (var i = gap; i < len; i++) {temp = arr[i];for (var j = i-gap; j >= 0 && arr[j] > temp; j-=gap) {arr[j+gap] = arr[j];}arr[j+gap] = temp;}}return arr;
}

 

六、归并排序

算法介绍:

作为一种典型的分而治之思想的算法应用,归并排序的实现由两种方法:

  1. 自上而下的递归(所有递归的方法都可以用迭代重写,所以就有了第2种方法)
  2. 自下而上的迭代

代码如下:

function merge_sort(arr) {  //采用自上而下的递归方法var len = arr.length;if(len < 2) {return arr;}var middle = Math.floor(len / 2),left = arr.slice(0, middle),right = arr.slice(middle);return merge(mergeSort(left), mergeSort(right));
}function merge(left, right)
{var result = [];while (left.length && right.length) {if (left[0] <= right[0]) {result.push(left.shift());} else {result.push(right.shift());}}while (left.length)result.push(left.shift());while (right.length)result.push(right.shift());return result;
}

归并排序动图演示 :

 

 七、堆排序

首先明白什么是堆,堆其实可以这么理解,类似金字塔,一层有一个元素,两层有两个元素,三层有四个元素,每层从数组中取元素,从左到右的顺序放到堆相应的位置上,也就是说每一层元素个数为2n-1 ;(n 代表行数),这就完成了建堆。

堆排序可以说是一种利用堆的概念来排序的选择排序。分为两种方法:

  1. 大顶堆:每个节点的值都大于或等于其子节点的值,在堆排序算法中用于升序排列
  2. 小顶堆:每个节点的值都小于或等于其子节点的值,在堆排序算法中用于降序排列

代码如下:

var len;    //因为声明的多个函数都需要数据长度,所以把len设置成为全局变量function buildMaxHeap(arr) {   //建立大顶堆len = arr.length;for (var i = Math.floor(len/2); i >= 0; i--) {
        heapify(arr, i);}
}function heapify(arr, i) {     //堆调整var left = 2 * i + 1,right = 2 * i + 2,largest = i;if (left < len && arr[left] > arr[largest]) {largest = left;}if (right < len && arr[right] > arr[largest]) {largest = right;}if (largest != i) {swap(arr, i, largest);heapify(arr, largest);}
}function swap(arr, i, j) {var temp = arr[i];arr[i] = arr[j];arr[j] = temp;
}function heapSort(arr) {buildMaxHeap(arr);for (var i = arr.length-1; i > 0; i--) {swap(arr, 0, i);len--;heapify(arr, 0);}return arr;
}

堆排序动图演示:

 

八、计数排序

算法介绍:
计数排序的核心在于将输入的数据值转化为键存储在额外开辟的数组空间中。
作为一种线性时间复杂度的排序,计数排序要求输入的数据必须是有确定范围的整数。

代码如下:

function counting_sort(arr, maxValue) {var bucket = new Array(maxValue+1),sortedIndex = 0;arrLen = arr.length,bucketLen = maxValue + 1;for (var i = 0; i < arrLen; i++) {if (!bucket[arr[i]]) {bucket[arr[i]] = 0;}bucket[arr[i]]++;}for (var j = 0; j < bucketLen; j++) {while(bucket[j] > 0) {arr[sortedIndex++] = j;bucket[j]--;}}return arr;
}

计数排序动图演示:

 

九、桶排序

桶排序是计数排序的升级版。它利用了函数的映射关系,高效与否的关键就在于这个映射函数的确定。
为了使桶排序更加高效,我们需要做到这两点:

  1. 在额外空间充足的情况下,尽量增大桶的数量
  2. 使用的映射函数能够将输入的N个数据均匀的分配到K个桶中

同时,对于桶中元素的排序,选择何种比较排序算法对于性能的影响至关重要。

什么时候最快(Best Cases):

当输入的数据可以均匀的分配到每一个桶中

什么时候最慢(Worst Cases):

当输入的数据被分配到了同一个桶中

代码演示:
function bucketSort(arr, bucketSize) {if (arr.length === 0) {return arr;}var i;var minValue = arr[0];var maxValue = arr[0];for (i = 1; i < arr.length; i++) {if (arr[i] < minValue) {minValue = arr[i];                //输入数据的最小值} else if (arr[i] > maxValue) {maxValue = arr[i];                //输入数据的最大值
      }}//桶的初始化var DEFAULT_BUCKET_SIZE = 5;            //设置桶的默认数量为5bucketSize = bucketSize || DEFAULT_BUCKET_SIZE;var bucketCount = Math.floor((maxValue - minValue) / bucketSize) + 1;   var buckets = new Array(bucketCount);for (i = 0; i < buckets.length; i++) {buckets[i] = [];}//利用映射函数将数据分配到各个桶中for (i = 0; i < arr.length; i++) {buckets[Math.floor((arr[i] - minValue) / bucketSize)].push(arr[i]);}arr.length = 0;for (i = 0; i < buckets.length; i++) {insertionSort(buckets[i]);                      //对每个桶进行排序,这里使用了插入排序for (var j = 0; j < buckets[i].length; j++) {arr.push(buckets[i][j]);                      }}return arr;
}

 

十、基数排序

基数排序须知:

基数排序有两种方法:

  1. MSD 从高位开始进行排序
  2. LSD 从低位开始进行排序
基数排序 vs 计数排序 vs 桶排序

这三种排序算法都利用了桶的概念,但对桶的使用方法上有明显差异:
基数排序:根据键值的每位数字来分配桶
计数排序:每个桶只存储单一键值
桶排序:每个桶存储一定范围的数值

 

代码演示:

function radix_sort(arr, maxDigit) {var mod = 10;var dev = 1;var counter = [];for (var i = 0; i < maxDigit; i++, dev *= 10, mod *= 10) {for(var j = 0; j < arr.length; j++) {var bucket = parseInt((arr[j] % mod) / dev);if(counter[bucket]== null) {counter[bucket] = [];}counter[bucket].push(arr[j]);}var pos = 0;for(var j = 0; j < counter.length; j++) {var value = null;if(counter[j]!=null) {while ((value = counter[j].shift()) != null) {arr[pos++] = value;}}}}return arr;
}

基数排序动图演示:

 



转载于:https://www.cnblogs.com/lhh520/p/10310908.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/364081.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[你必须知道的.NET] 第一回:恩怨情仇:is和as

发布日期&#xff1a;2007.4.7 作者&#xff1a;Anytao ©2007 Anytao.com 转贴请注明出处&#xff0c;留此信息。 本文将介绍以下内容&#xff1a; • 类型转换 • is/as操作符小议 1. 引言 类型安全是.NET设计之初重点考虑的内容之一&#xff0c;对于程序设计者来说&…

获取当前鼠标的位置以及组件的位置

总结&#xff1a; div如果要触发鼠标事件要加上css样式cusor:pointer。 更多专业前端知识&#xff0c;请上 【猿2048】www.mk2048.com

谷歌推大语言模型VideoPoet:文本图片皆可生成视频和音频

Google Research最近发布了一款名为VideoPoet的大型语言模型&#xff08;LLM&#xff09;&#xff0c;旨在解决当前视频生成领域的挑战。该领域近年来涌现出许多视频生成模型&#xff0c;但在生成连贯的大运动时仍存在瓶颈。现有领先模型要么生成较小的运动&#xff0c;要么在生…

PyCon大会Python主题演讲摘要

PyCon 是全国际最大的以 Python 编程言语 为主题的技能大会。大会由 Python 社区组织&#xff0c;每年举行一次。在大会上&#xff0c;来自国际各地的 Python 用户与中心开发者齐聚一堂&#xff0c;共同同享 Python 国际的新鲜事、Python 言语的应用案例、运用技巧等等内容。 I…

欢迎使用Java 8之前要重温的10个JDK 7功能

Java 8发布已经快一个月了&#xff0c;我敢肯定&#xff0c;大家都在探索JDK 8的新功能。但是&#xff0c;在您完全研究Java 8之前&#xff0c;是时候重新审视Java 7上引入的一些很棒的功能了。记住&#xff0c;Java 6并没有什么功能&#xff0c;它只与JVM的更改和性能有关&…

java版本号管理_微服务项目中如何管理依赖版本号?

本文是微服务项目代码组织形式三部曲中的第三篇&#xff0c;也是最后一篇&#xff0c;通过这三篇文章&#xff0c;相信大家对于如果组织微服务中的代码已经有了一个基本认知&#xff0c;前面两篇分别是&#xff1a;第三篇相对来说要简单一些&#xff0c;本来没打算写&#xff0…

对于刚开始使用该软件,应该在熟悉基本的markdown语法的基础上,再进行快捷键的使用!...

一级标题 # 空格 编写内容 二级标题 ## 空格 编写内容 有序内容 1.Tab 无序内容 -Tab 代码块 print("hello wrold") typora快捷键 ctrl1一级标题 添加图片 表格 CtrlT 姓名年龄职业谢国宏20IT文字加粗 24期的小伙伴们你们好 文字斜体 你好 又粗又斜 粗斜* 3**2 -- 幂…

struct和byte[]相互转换(用Marshal类实现)

转自[DotNet笔记]相当于序列化与反序列化&#xff0c;但是不用借助外部文件1、struct转换为byte[] 1staticbyte[] StructToBytes(objectstructObj) 2{ 3 int size Marshal.SizeOf(structObj); 4 IntPtr buffer Marshal.AllocHGlobal(size); 5 …

Get-CrmSetting返回Unable to connect to the remote server的解决办法

摘要: 微软动态CRM专家罗勇 &#xff0c;回复302或者20190125可方便获取本文&#xff0c;同时可以在第一间得到我发布的最新博文信息&#xff0c;follow me&#xff01;我的网站是 www.luoyong.me 。 在Dynamics 365部署管理器所在的服务器上执行Get-CrmSetting&#xff0c;最近…

java 二维数组奇数金字塔_二维数组:奇数阶魔方 | 新思维:C语言程序设计

幻方&#xff0c;有时又称魔方&#xff0c;由一组排放在正方形中的整数组成&#xff0c;其每行、每列以及两条对角线上的数之和均相等。通常幻方由从到的连续整数组成。Siamese方法(Kraitchik 1942年&#xff0c;pp. 148-149)是构造奇数阶幻方的一种方法&#xff0c;说明如下&a…

拷贝构造函数与赋值函数(运算符重载)(1)

拷贝构造函数拷贝构造函数在三种情况下会被使用1.使用对象来初始化对象时2.当函数的形参是对象时3.当函数的返回值为对象时 2,3情况的本质还是1 //Test1.h #include<iostream> using namespace std; class ST { private:int a;long b; public:ST(int a0, long b0):a(a),…

GOOGLE不让我访问啦?

GOOGLE不让我访问啦? 今天上GOOGLE出现了这么一个画面,可是我就是不知道我的电脑到底中了什么毒,平常我没上什么特殊的网站,也没下载什么软件,因为这电脑我只用来做些基本的开发和看看园子里的文章而已.真不知道是怎么一回事.posted on 2007-05-05 12:46 黄尚 阅读(...) 评论(…

java条件执行方法_java 开启多线程里面如何加条件判断执行其他逻辑?

方法1&#xff1a;通过Thread类中的isAlive()方法判断线程是否处于活动状态。线程启动后&#xff0c;只要没有运行完毕&#xff0c;都会返回true。【注】如果只是要等其他线程运行结束之后再继续操作&#xff0c;可以执行t.join()&#xff0c;即&#xff1a;在t执行完毕前挂起。…

大数据分析和人工智能科普

一、大数据 1.1 大数据&#xff08;Big Data&#xff09; 众说纷纭&#xff01; 个人认为&#xff0c;大数据中的“大”&#xff0c;不仅仅是涉及数据规模&#xff0c;而且包含“价值“这个层面。其实无非就是大量的信息罢了&#xff0c;但是我们却能 通过各种手段从这些信息中…

Redis API的使用与理解

一、Redis 基础&#xff1a; 1、通用命令&#xff1a; keys [pattern]&#xff1a; keys * #遍历所有key&#xff1b;keys he* #以he开头的key&#xff1b; keys he[a-e]* #以‘he’开头第三个字母是a-e之间&#xff1b; keys ph? #?代码一位&#xff0c;以ph开头且字母是…

点击底部input输入框,弹出的软键盘挡住input(苹果手机使用第三方输入法 )

测试移动端页面的时候&#xff0c;偶然发现点击底部input输入框时&#xff0c;弹出的虚拟键盘偶尔会挡住input输入框。 输入框固定在页面底部&#xff0c;如图所示&#xff1a; input固定底部设计图.png点击底部input输入框唤起软键盘时&#xff0c;软键盘挡住输入框。如图所示…

java采集温湿度水浸_机房水浸传感器:智能生活不可或缺的漏水传感器

原标题&#xff1a;机房水浸传感器&#xff1a;智能生活不可或缺的漏水传感器智能化的飞速发展让人们的生活发生了重大改变&#xff0c;为保证机房的安全、稳定、高效运行&#xff0c;网络设备的良好运行状态和设备使用寿命与安全&#xff0c;通常会对网络运行环境的电力供应、…

创建型模式:原型模式

个人公众号原文&#xff1a;创建型模式&#xff1a;原型模式 五大创建型模式之五&#xff1a;原型模式。 简介 姓名 &#xff1a;原型模式 英文名 &#xff1a;Prototype Pattern 价值观 &#xff1a;效率第一 个人介绍 &#xff1a; Specify the kinds of objects to create u…

我的前端工具集(五)提示工具之模态窗提示

我的前端工具集&#xff08;五&#xff09;提示工具之模态窗提示 liuyuhang原创&#xff0c;未经允许禁止转载 目录 我的前端工具集 1、需求 很多页面操作都需要提示&#xff0c;比如操作成功&#xff0c;操作失败之类。 总不能没事就console.log或者alert吧。 所以一个操作提…

Java 8 Friday:可选将保留为Java中的一个选项

在Data Geekery &#xff0c;我们喜欢Java。 而且&#xff0c;由于我们真的很喜欢jOOQ的流畅的API和查询DSL &#xff0c;我们对Java 8将为我们的生态系统带来什么感到非常兴奋。 Java 8星期五 每个星期五&#xff0c;我们都会向您展示一些不错的教程风格的Java 8新功能&#…