一、冒泡排序

  原理:1.比较相邻的元素。如果第一个比第二个大,就交换两个数;2.对每一对相邻元素重复做步骤一,从开始第一对到结尾的最后一对,该步骤结束会产生一个最大的数;3.针对所有的数重复以上的步骤(最后一个数除外);4.持续每次对越来越少的数重复上面步骤,直到没有任何一对数需要比较。

 function bubbleSort(arr) {
let len = arr.length
// 外层循环为执行次数
for (let i = 0; i < len - 1; i++) {
// 外层循环为相邻两个数的比较
for (let j = 0; j < len - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
sort(arr, j, j + 1)
}
}
}
return arr } function sort(arr, i, j) {
let temp = arr[i]
arr[i] = arr[j]
arr[j] = temp
}
let arr = [1, 5, -3, 8, 10]
console.log(bubbleSort(arr)) // [-3, 1, 5, 8, 10]

二、选择排序。

  原理:1.首先在末拍序列中找到最小(大)值,存方法到排序序列的起始位置;2.再从剩余末排序列中继续寻找最小(大)值,然后放到已排序序列的末尾;3.重复步骤二,直到所有元素均排序完毕。

即:将数组中第一个数标记,然后依次和后面的数进行比较,若找到比标记的数大(小)时再将该数进行标记往后找,直到比较完后再进行位置交换

 function selectSort(arr){
let len = arr.length,
minIndex,temp;
for(let i = 0;i < len - 1;i++){
minIndex = i;
for(let j = i + 1;j < len;j++){
if(arr[j] < arr[minIndex]){
minIndex = j;
}
}
temp = arr[i];
arr[i] = arr[minIndex];
arr[minIndex] = temp;
}
return arr;
}
let arr = [3,8,9,4,3,0,7] // [0, 3, 3, 4, 7, 8, 9]
console.log(selectSort(arr))

三、插入排序

  原理:1.将第一待排序列第一个元素看做一个有序序列,把第二个元素到最后一个函数当成是未排序序列;2.从头到尾依次扫描未排序序列,将扫描到的每个元素插入有序序列的适当位置(如果待插入的元素与有序序列中某个元素相等,则将待插入元素插入到相等元素的后面)。

  个人认为该排序算法相对容易理解,哈哈!!!

  function insertSort(arr){
let len = arr.length,
preIndex,current;
for(let i = 1;i < len;i++){
preIndex = i -1;
current = arr[i];
while(preIndex >= 0 && arr[preIndex] > current){
arr[preIndex + 1] = arr[preIndex];
preIndex--
}
arr[preIndex + 1] = current;
}
return arr;
}
let arr = [-5,8,10,99,21,3];
console.log(insertSort(arr)) // [-5, 3, 8, 10, 21, 99]

四、希尔排序

  原理:先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录“基本有序”时,再对全体记录进行依次直接插入排序

 function shellSort(arr){
var gap = arr.length;
while(gap>1){
gap = parseInt(gap/2);
for(var j=gap;j<arr.length;j++){
var temp = arr[j];
var i = j-gap;
while(arr[i]>temp && i>=0){
arr[i+gap] = arr[i];
i = i-gap;
}
arr[i+gap] = temp;
}
}
return arr;
}
let arr = [4, 2, 9, 1, 6, 8];
console.log(shellSort(arr)) // [1, 2, 4, 6, 8, 9]

例如:

 var arr = [3,44,38,5,47,15,36,26,27,2,46,4,19,50,1];
第一次,增量为7,则分割为:
1-->[3, 26, 1]
2-->[44, 27]
3-->[38, 2]
4-->[5, 46]
5-->[47, 4]
6-->[15, 19]
7-->[36, 50]
进行排序后结果为:
[1, 27, 2, 5, 4, 15, 36, 3, 44, 38, 46, 47, 19, 50, 26]
第二次,增量为3,则分割为:
1-->[1,5, 36, 38, 19]
2-->[27, 4, 3, 46, 50]
3-->[2, 15, 44, 47, 26]
进行排序后结果为:
[1, 3, 2, 5, 4, 15, 19, 27, 26, 36, 46, 44, 38, 50, 47]
第三次,增量为1,进行排序后为:
[1, 2, 3, 4, 5, 15, 19, 26, 27, 36, 38, 44, 46, 47, 50]

五、归并排序

  原理:1.把长度为n的输入序列分成两个长度为n/2的子序列;2.对这两个子序列分别采用归并排序;3.将两个排序好的子序列合并成一个最终的排序序列。

     function mergeSort(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;
}
var arr = [2,5,1,6,-4,10]
// let arr = [2,1]
console.log(mergeSort(arr))   // [-4,1,2,5,6,10]

六、快速排序

  原理:1.从数列中选出一个数以该数为‘基准’;2.重新排序数列,所有元素比基准值小的排在前面,比基准值大的排在后面(和基准值相等的数可放在任何一边)。在这个分区退出后,该基准就处于数列的中间位置,这个称为分区操作;3.递归地把小于基准值元素的子数列和大于基准值元素的子数列排序。

  中心思想:通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。

 function quickSort(arr){
var len = arr.length
if(len <= 2){
return arr;
}
var middle = parseInt(len / 2),
base = arr[middle],
left = [],
right = [];
for(var i = 0;i < len;i++){
if(i === middle){
continue;
}
if(arr[i] < base){
left.push(arr[i]);
}
else{
right.push(arr[i])
}
}
return quickSort(left).concat(base,quickSort(right))
} var arr = [2, 9, 1, -5, -10, 6, 8, 7]
console.log(quickSort(arr)) // [-10, -5, 2, 1, 6, 7, 8, 9]

七、堆排序

  原理:1.将初始待排序关键字序列(R1,R2,...Rn)构建成大顶堆,此堆为初始堆无无序区;2.将堆顶元素R[1]与最后一个元素R[n]交换,此时得到新堆无序区(R1,R2,...,Rn-1)和新堆有序区(Rn),且满足R[1,2,...,n-1]<R[n];3.由于交换后新堆堆顶R[1]可能违反堆的性质,因此需要堆当前无序区(R1,R2,...,Rn-1)调整为新堆,然后再次将R[1]与无序区最后一个元素交换,得到新的无序区(R1,R2,...,Rn-2)和新的有序区(Rn-1,Rn)。不断重复此过程,知道有序区的元素个数为n-1,则整个排序过程完成。

  中心思想:利用这种数据结构设计的一种算法,即自己点的键值或索引总是小于(或大于)它的父节点。

     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;
}
var arr = [1, 2, 6, 8, 11, -7, 20]
console.log(heapSort(arr)) // [-7, 1, 2, 6, 8, 11, 20]

八、计数排序

  原理:1.找出待排序对数组中最大和最小对元素;2.统计数组中每个值为i的元素出现的次数,存入数组C的第i项;3.对所有的计数累加(从C中的第一个元素开始,每一项和前一项相加);4.反向填充目标数组,将每个元素i放在心数组的第C(i)项,每放一个元素就将C(i)减去i;

  中心思想:使用额外的数组C,其中第i个元素时待排序数组A中值等于i的元素的个数,然后根据数组C来将A中的元素排到正确的位置,它只能对正整数进行排序。

  function countingSort(arr) {
var len = arr.length;
var min = max = arr[0],
result = [];
for (var i = 1; i < len; i++) {
max = arr[i] > max ? arr[i] : max;
min = arr[i] < min ? arr[i] : min;
}
var newArr = new Array(max + 1);
newArr.fill(0);
for (var i = 0; i < len; i++) {
newArr[arr[i]] = ++newArr[[arr[i]]];
}
for (var i = min - 1; i < max + 1; i++) {
if (newArr[i] != 0) {
while (newArr[i]) {
result.push(i);
--newArr[i];
}
}
}
return result;
} var arr = [2, 4, 6, 1, 7, 33, 50, 8]
console.log(countingSort(arr)) // [1, 2, 4, 6, 7, 8, 33, 50]

九、桶排序

  原理:1.设置一个定量的数组,当做 “空桶”;2.遍历输入数据,并且把数组一个一个放到对应的桶里去;3.对每个不是空桶进行排序;4.从不是空的桶里把排好序的数据拼接起来。

  中心思想:计数排序的升级版。假设输入数据服从均匀分布,则数据分到有限数量到桶里,没每个桶再分别排序(有可能再使用别的排序或是以递归方法继续使用桶排序进行排序)

 function bucketSort(arr, num = 5) {
var len = arr.length;
if (len < 2 || singleArray(arr)) {
return arr;
}
var min = max = arr[0],
result = [];
var temp = new Array(num);
for (var i = 0; i < num; i++) {
temp[i] = [];
}
for (var i = 0; i < len; i++) {
max = arr[i] > max ? arr[i] : max;
min = arr[i] < min ? arr[i] : min;
}
var gap = (max - min + 1) / num;
for (var i = 0; i < len; i++) {
var index = parseInt((arr[i] - min) / gap);
temp[index].push(arr[i]);
}
temp = temp.filter(function (item) {
return item.length;
});
var tempLen = temp.length;
for (var i = 0; i < tempLen; i++) {
temp[i] = bucketSort(temp[i]);
result = result.concat(temp[i]);
}
return result;
} function singleArray(arr) { // 判断数组各项是否相同
var len = arr.length;
for (var i = 1; i < len; i++) {
if (arr[i] != arr[0]) {
return false;
}
}
return true;
} var arr = [1, 3, 8, -6, 11, 7, 99]
console.log(bucketSort(arr, 5)) // [-6, 1, 3, 7, 8, 11, 99]

例:

 var arr = [98,89, 89,1,2,3];
(1)设置桶的数量为5,找到最大值98,最小值1,每个桶的范围(98-1+1)/5=19.6
(2)遍历原始数据,以连标结构放到对应的桶中,数组98,索引值为4(=parseInt(98-1)/19.6),数字89索引值为4(=parseInt(89-1)/19.6),数字1,2,3的索引都为0
桶0–>[1,2,3]
桶1–>[]
桶2–>[]
桶3–>[]
桶4–>[98,89,89]
(3)过滤掉为空的桶
(4)递归地利用桶排序(或者其他排序方法)对各个桶中的数组进行排序,如果数组长度为1,或者数组中各项相同(至关重要),则直接返回数组
(5)将各桶合并

十、基数排序

  原理:1.取得数组中的最大值,并取得位数;2.arr为原始数组,从最低位开始取每个位组成radix数组;3.对radix进行计数排序(利用计数排序适用于小范围的特点)

  中心思想:按照低位先排序,然后收集;再按照高位排序,然后再收集;依次类推,直到最高位。

  注:计数排序使用数据范围较小(建议小于1000,且每个数值都要大于0)

 function radixSort(arr) {
var len = arr.length;
var max = arr[0],
dev = 1,
mod = 10;
for (var i = 1; i < len; i++) {
max = arr[i] > max ? arr[i] : max;
}
var radix = max.toString().length;
for (var j = 1; j <= radix; j++) {
var result = [];
var temp = new Array(10);
for (var i = 0; i < 10; i++) {
temp[i] = [];
}
for (var i = 0; i < len; i++) {
var pos = parseInt(arr[i] % mod / dev);
temp[pos].push(arr[i]);
}
dev *= 10;
mod *= 10;
for (var i = 0; i < 10; i++) {
result = result.concat(temp[i]);
}
arr = result;
}
return arr;
}
var arr = [3,6,4,22,12,69]
console.log(radixSort(arr)) // [3, 4, 6, 12, 22, 69]

排序算法复杂度比较

n:数据规模

k:‘桶’的个数

In-place:占用常数内存,不占用额外内存

Out-place:占用额外内存

稳定:假如 a 在 b 前面,而 a == b,排序之后 a 依然在 b 前面

不稳定:假如 a 在 b 前面,而 a == b,排序之后 a 可能就在 b后面

JavaScript之排序算法的更多相关文章

  1. JavaScript版排序算法

    JavaScript版排序算法:冒泡排序.快速排序.插入排序.希尔排序(小数据时,希尔排序会比快排快哦) //排序算法 window.onload = function(){ var array = ...

  2. javascript高级排序算法之快速排序(快排)

    javascript高级排序算法之快速排序(快排)我们之前讨论了javascript基本排序算法 冒泡排序 选择排序 插入排序 简单复习: 冒泡排序: 比较相邻的两个元素,如果前一个比后一个大,则交换 ...

  3. javascript常用排序算法实现

    毕业后,由于工作中很少需要自已去写一些排序,所以那些排序算法都忘得差不多了,不过排序是最基础的算法,还是不能落下啦,于是找了一些资料,然后用Javascript实现了一些常用的算法,具体代码如下: & ...

  4. javascript常用排序算法总结

    算法是程序的灵魂.虽然在前端的开发环境中排序算法不是很经常用到,但常见的排序算法还是应该要掌握的.我在这里从网上整理了一下常见排序算法的javascript实现,方便以后查阅. 归并排序: 1 fun ...

  5. javascript的排序算法

    已经准备秋招一段时间了,因为这个关系也在各种巩固知识,顺便整理一下一些东西.这篇文章就是自己整理了一下各种JS的排序算法,以便自己以后回顾. 冒泡排序 function bubbleSort(arr) ...

  6. JavaScript 实现排序算法

    参考文章: 十大经典排序算法动画,看我就够了! 1. 冒泡排序 思路 比较所有相邻元素,如果第一个比第二个大,则交换它们 一轮下来,可以保证最后一个数是最大的 执行n-1轮,就可以完成排序 代码 Ar ...

  7. JavaScript随机排序算法1

    1.对数组循环,每一项与随机的某一项位置调换 <ul id="listOne"></ul> <div id="tempOne"&g ...

  8. JavaScript实现排序算法总结

    <script type="text/javascript" src="js/laydate.js" > //插入排序 function inser ...

  9. javascript实现排序算法

    准备好好学习js了,js写的第一个排序 先推荐一个js在线编辑工具,RunJS,还不错. 冒泡排序 var arr = [2,4,1,5,3]; function handle(arr){ for(v ...

随机推荐

  1. linux下什么工具可以用来纠正文件中的拼写和排版错误?

    答: ispell,官网在此

  2. <JavaScript> 普通函数与构造函数的区别

    JavaScript中存在构造函数与函数两个概念. 这可能会给初学者造成一定的困扰,难不成存在两种函数. 然而事实这两种函数的构成完全一样,无论从长相还是气质都是一模一样的. 区别点在于,所扮演觉得不 ...

  3. kotlin之操作符重载

    一元操作符 表达式 对应的函数 +a a.unaryPlus() -a a.unaryMinus() !a a.not() a++ a.inc() a-- a.dec() fun main(arg: ...

  4. C之指针

    什么是指针 * 指针变量:用来存储某种数据在内存中的地址.* 世面上书籍一般把指针和指针变量的概念混在一起了.市面上的书籍说的指针指的就是指针变量 Ø *号的三种含义1. 两个数相乘int i =5; ...

  5. zookeeper-3.5.5安装报错:找不到或无法加载主类 org.apache.zookeeper.server.quorum.QuorumPeerMain

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明.本文链接:https://blog.csdn.net/jiangxiulilinux/artic ...

  6. 002-多线程-JUC集合-List-CopyOnWriteArrayList

    一.概述 CopyOnWriteArrayList是Java并发包中提供的一个并发容器,它是个线程安全且读操作无锁的ArrayList,写操作则通过创建底层数组的新副本来实现,是一种读写分离的并发策略 ...

  7. Qt编写数据可视化大屏界面电子看板6-窗体打开关闭

    一.前言 二级窗体的打开与关闭,这个功能也很有必要,由于整个系统中各种模块数量窗体数量比较多,后期可能还会增加更多,在4K屏幕上可以显示很多的模块,但是有时候有些模块不想显示出来,就需要将该模块关闭掉 ...

  8. Docker使用Portainer搭建可视化界面

    Portainer介绍 Portainer是Docker的图形化管理工具,提供状态显示面板.应用模板快速部署.容器镜像网络数据卷的基本操作(包括上传下载镜像,创建容器等操作).事件日志显示.容器控制台 ...

  9. IDEA配置Hystrix过程中报错: java.lang.IllegalStateException: No instances available for user-service

    最近在练习微服务架构中, 使用IDEA配置完Hystrix, 添加熔断方法后, 在浏览器中访问未启动的( 含有熔断方法注解 )的路径时, 报出了 : 500: No instances availab ...

  10. 交换分区swap

    一.查看当前的交换分区[root@server0 ~]# free      -mtotal used free shared buff/cache availableMem: 489 140 145 ...