首先生成一个数字数组:

let arr = Array.from({length:20},x=>{return Math.ceil(Math.random()*10**2)})
console.log(arr)
function fn(a,b){
return a-b;
} // console.log(arr.sort(fn))
// 十大排序
// 1.冒泡排序(Bubble Sort)
// 冒泡排序是一种简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。
// 走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。
// 这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。
function bubbleSort(a){
let k = 0;
let h = 0;
for(var i=0;i<a.length;i++){
for(var j=i+1;j<a.length;j++){
k++;
if(a[i] > a[j]){
h++;
[a[i],a[j]] = [a[j],a[i]];
}
}
}
console.log('o=',k,'h=',h);
return a;
}
console.log('bubbleSort', bubbleSort([].concat(arr)) ) function bubbleSort1(arr) {
var len = arr.length;
let k = 0;
let h = 0;
for (var i = 0; i < len; i++) {
for (var j = 0; j < len - 1 - i; j++) {
k++;
if (arr[j] > arr[j+1]) { //相邻元素两两对比
h++;
[arr[j+1],arr[j]] = [arr[j],arr[j+1]];
}
}
}
console.log('o=',k,'h=',h);
return arr;
}
console.log('bubbleSort1', bubbleSort1([].concat(arr)) )

// 2. 选择排序(Selection Sort)
// 在时间复杂度上表现最稳定的排序算法之一,因为无论什么数据进去都是O(n²)的时间复杂度。。。
// 所以用到它的时候,数据规模越小越好。唯一的好处可能就是不占用额外的内存空间了吧
// 首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,
// 然后,再从剩余未排序元素中继续寻找最小(大)元素,
// 然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。
function selectionSort(a){
let k = 0;
let h = 0;a
for(var i=0;i<a.length;i++){
let tmp = a[i];
let pos = i;
for(var j=i+1;j<a.length;j++){
k++;
if(tmp>a[j]){
tmp=a[j];
pos = j;
h++;
}
}
if(tmp<a[i]){
[a[i], a[pos]] = [a[pos],a[i]];
}
} console.log('o=',k,'h=',h);
return a;
}
console.log('selectionSort', selectionSort([].concat(arr)) )

// 3. 插入排序(Insertion Sort)
// 工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,
// 找到相应位置并插入。插入排序在实现上,通常采用in-place排序(即只需用到O(1)的额外空间的排序),
// 因而在从后向前扫描过程中,需要反复把已排序元素逐步向后挪位,为最新元素提供插入空间。
function insertionSort(arr){
let k=0;
let h=0;
for(var i=1;i<arr.length;i++){
let j = i;
let cur = arr[i];
let flag = false;
while(j>=0 && arr[j-1] > cur){
k++;
h++;
arr[j] = arr[j-1];
j--;
flag=true;
}
if(!flag){
k++;
}
arr[j]=cur;
}
console.log('o=',k,'h=',h);
return arr;
}
let insertArr = insertionSort([].concat(arr));
console.log('insertionSort', insertArr)
console.log('insertionSort', insertionSort(insertArr))
console.log('insertionSort', insertionSort(insertArr.reverse())) function insertionSort1(arr){
let k=0;
let h=0;
for(var i=1;i<arr.length;i++){
let cur = arr[i];
let left = 0;
let right = i-1;
while(left <= right){
k++;
let mid = parseInt((right+left)/2);
if(arr[mid] > cur){
right = mid -1;
}else{
left = mid + 1;
}
}
for(var j=i-1;j>=left;j--){
h++;
k++;
arr[j+1]=arr[j];
}
arr[left] = cur;
}
console.log('o=',k,'h=',h);
return arr;
} let insertArr1 = insertionSort1([].concat(arr));
console.log('insertionSort1', insertArr1)
console.log('insertionSort1', insertionSort1(insertArr1))
console.log('insertionSort1', insertionSort1(insertArr1.reverse()))
// 4. 希尔排序(Shell Sort)
// 希尔排序是插入排序的一种更高效率的实现。它与插入排序的不同之处在于,它会优先比较距离较远的元素。
// 希尔排序的核心在于间隔序列的设定。既可以提前设定好间隔序列,也可以动态的定义间隔序列
function shellSort(a){
let len = a.length;
let gap = 1;
let k=0;
let h=0
while(gap<(len/3)){
gap = gap*3+1;
}
for(gap;gap>0;gap=Math.floor(gap/3) ){
for(var i=gap;i<len;i++){
let cur = a[i];
for(var j=i-gap;j>=0 && cur < a[j];j-=gap){
k++;
h++;
a[j+gap] = a[j];
}
a[j+gap] = cur;
}
}
console.log('o=',k,'h=',h);
return a;
} let shellArr = shellSort([].concat(arr));
console.log('shellSort', shellArr)
console.log('shellSort', shellSort(shellArr))
console.log('shellSort', shellSort(shellArr.reverse()))
// 5. 归并排序(Merge Sort)
// 归并排序是一种稳定的排序方法。将已有序的子序列合并,得到完全有序的序列;
// 即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为2-路归并
// 递归 recursion
function merge(a,b){
let len1 = a.length;
let len2 = b.length;
let i=0,j=0;
let ret = [];
while(i<len1 && j<len2){
if(a[i]<b[j]){
ret.push(a[i]);
i++;
}else{
ret.push(b[j]);
j++;
}
}
if(i<len1){
ret = ret.concat(a.slice(i));
}
if(j<len2){
ret = ret.concat(b.slice(j));
}
return ret;
}
function mergeSort(a){
let len = a.length;
if(len == 1){
return a;
}
let mid=parseInt(len/2);
let left = a.slice(0,mid);
let right = a.slice(mid);
return merge(mergeSort(left),mergeSort(right));
} let mergeArr = mergeSort([].concat(arr));
console.log('mergeSort', mergeArr)
console.log('mergeSort', mergeSort(mergeArr))
console.log('mergeSort', mergeSort(mergeArr.reverse())) // 非递归
function mergeSort1(a){
let gap = 3;
let k=0;
for(gap;gap<a.length;gap=2*gap){
for(var i=0;i<a.length;i+=gap){
let r = [];
k++;
if((i+gap)>a.length){
r = merge(a.slice(i),[]);
}else{
let mid = parseInt((i+i+gap)/2);
let left = a.slice(i,mid);
let right = a.slice(mid,i+gap);
r = merge(left,right);
}
a.splice(i,r.length,...r);
}
if(gap*2>a.length){
a = merge(a.slice(0,gap),a.slice(gap, a.length));
}
}
console.log('k=',k)
return a;
} let mergeArr1 = mergeSort1([].concat(arr));
console.log('mergeSort1', mergeArr1)
console.log('mergeSort1', mergeSort1(mergeArr1))
console.log('mergeSort1', mergeSort1(mergeArr1.reverse()))
// 6. 快速排序(Quick Sort)
// 又是一种分而治之思想在排序算法上的典型应用。本质上来看,快速排序应该算是在冒泡排序基础上的递归分治法
//基本思想:通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,
// 则可分别对这两部分记录继续进行排序,以达到整个序列有序
function quickSort(a){
if(a.length <= 1) return a;
let pivotIndex = Math.ceil(a.length/2);
let pivot = a.splice(pivotIndex,1)[0];
let left=[];
let right=[];
let k=0;
for(var i=0;i<a.length;i++){
k++;
if(a[i]<pivot){
left.push(a[i]);
}else{
right.push(a[i]);
}
}
console.log('k=',k)
return quickSort(left).concat([pivot],quickSort(right));
}
let quickArr = quickSort([].concat(arr));
console.log('quickSort', quickArr) function partition(a,left,right){
let pivot=a[right];
let i=left;
for(var j=left;j<=right;j++){
if(a[j]<pivot)
{
[a[i], a[j]]=[a[j],a[i]];
i++;
}
}
[a[i],a[right]]=[a[right],a[i]];
return i;
}
function quickSort1(a, left, right){
if(left<right){
let i = partition(a,left,right);
quickSort1(a,left,i-1);
quickSort1(a, i+1, right); }
return a;
} let quickArr1 = quickSort1([].concat(arr), 0, arr.length-1);
console.log('quickSort1', quickArr1);
// 7.堆排序(Heap Sort)
// 堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点
function buildMaxHeap(a){
let len = a.length;
for(var i=Math.floor(len/2);i>=0;i--){
heapify(a,i,len);
} return a;
}
function heapify(a,i,len){
let left = 2*i+1;
let right = 2*i+2;
let largest = i;
if(left<len && a[left] > a[largest]){
largest = left;
}
if(right<len && a[right] > a[largest]){
largest = right;
}
if(largest != i){
[a[largest],a[i]] = [a[i],a[largest]];
heapify(a,largest,len);
}
}
function heapSort(a){
let len = a.length;
buildMaxHeap(a);
for(var i=(len-1);i>=0;i--){
[a[i],a[0]] = [a[0],a[i]];
heapify(a,0,--len);
}
return a;
} let heapArr1 = heapSort([].concat(arr), 0, arr.length-1);
console.log('heapSort', heapArr1);
// 8.计数排序(Counting Sort)
// 计数排序的核心在于将输入的数据值转化为键存储在额外开辟的数组空间中。
function countingSort(a){
let max = 0;
let len = a.length;
let k=0; for(var i=0;i<len;i++){
if(max<a[i]){
max=a[i];
}
k++;
}
let bucket = new Array(max+1); for(var i=0;i<len;i++){
if(!bucket[a[i]]){
bucket[a[i]] = 0;
}
bucket[a[i]]++;
k++;
}
let h=0; // for(var j=1;j<max+1;j++){
// while(bucket[j]>0){
// a[h++] = j;
// bucket[j]--;
// }
// k++;
// }
// bucket.forEach((val,index)=>{
// while(val>0){
// a[h++] = index;
// val--;
// }
// k++;
// }) bucket.map((val,index)=>{
while(val>0){
a[h++] = index;
val--;
}
k++;
})
console.log('k=',k,h)
return a;
}
let countingArr1 = countingSort([].concat(arr), 0, arr.length-1);
console.log('countingSort', countingArr1);
// 9 桶排序(Bucket Sort)
// 桶排序是计数排序的升级版
// 它利用了函数的映射关系,高效与否的关键就在于这个映射函数的确定
function bucketSort(a){
let max = 0;
let min = 0;
let len = a.length;
let size = Math.ceil(len/3);
let count = 0;
for(var i=0;i<len;i++){
if(a[i]<min){
min = a[i];
}
if(a[i]>max){
max = a[i];
}
count++;
}
let bucketLen = Math.floor( (max-min)/size );
let bucket = new Array(bucketLen+1);
for(var j=0;j<bucketLen+1;j++){
bucket[j] = [];
count++;
}
for(var k=0;k<len;k++){
bucket[Math.floor((a[k]-min)/size)].push(a[k]);
count++;
} a.length = 0;
for(var l=0;l<bucketLen+1;l++){
countingSort(bucket[l]);
if(bucket[l].length>0){
a.push(...bucket[l]);
}
count++;
} console.log('count=',count);
return a;
} let bucketArr1 = bucketSort([].concat(arr), 0, arr.length-1);
console.log('bucketSort', bucketArr1);
// 10. 基数排序(Radix Sort)
// 基数排序:根据键值的每位数字来分配桶
// 计数排序:每个桶只存储单一键值
// 桶排序:每个桶存储一定范围的数值
function radixSort(a){
let bucket = new Array(11);
let max = Math.max(...a);
let len = max.toString().length;
let arrLen = a.length;
let count=0;
let rest = []; for(var i=0;i<len;i++){
bucket.length = 0;
for(var j=0;j<a.length;j++){
let str = a[j].toString();
if(str.length>i){
let index = str[str.length-1-i];
if(bucket[index] == null){
bucket[index] = [];
}
bucket[index].push(a[j]);
count++;
}else{
rest.push(a[j]);
}
}
a.length = 0;
bucket.forEach((val,index)=>{
a.push(...bucket[index]);
count++;
})
}
if(a.length<arrLen){
a=[].concat(rest,a);
}
console.log('count = ',count);
return a;
} let radixtArr1 = radixSort([].concat(arr), 0, arr.length-1);
console.log('radixSort', radixtArr1);

参考:

https://www.cnblogs.com/onepixel/p/7674659.html

https://www.cnblogs.com/jztan/p/5878630.html

https://www.cnblogs.com/vali/p/7803243.html

javascript 十大经典排序的更多相关文章

  1. JavaScript十大经典排序算法

    排序算法说明 (1)排序的定义:对一序列对象根据某个关键字进行排序: 输入:n个数:a1,a2,a3,…,an输出:n个数的排列:a1’,a2’,a3’,…,an’,使得a1’ 再讲的形象点就是排排坐 ...

  2. JavaScript 数据结构与算法之美 - 十大经典排序算法汇总(图文并茂)

    1. 前言 算法为王. 想学好前端,先练好内功,内功不行,就算招式练的再花哨,终究成不了高手:只有内功深厚者,前端之路才会走得更远. 笔者写的 JavaScript 数据结构与算法之美 系列用的语言是 ...

  3. 十大经典排序算法的 JavaScript 实现

    计算机领域的都多少掌握一点算法知识,其中排序算法是<数据结构与算法>中最基本的算法之一.排序算法可以分为内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大 ...

  4. 十大经典排序算法(Javascript实现)

    前言 总括: 本文结合动图详细讲述了十大经典排序算法用Javascript实现的过程. 原文博客地址:十大经典排序算法 公众号:「菜鸟学前端」,回复「666」,获取一揽子前端技术书籍 人生有情泪沾衣, ...

  5. 十大经典排序算法(python实现)(原创)

    个人最喜欢的排序方法是非比较类的计数排序,简单粗暴.专治花里胡哨!!! 使用场景: 1,空间复杂度 越低越好.n值较大: 堆排序 O(nlog2n) O(1) 2,无空间复杂度要求.n值较大: 桶排序 ...

  6. 十大经典排序算法+sort排序

    本文转自:十大经典排序算法,其中有动图+代码详解,本文简单介绍+个人理解. 排序算法 经典的算法问题,也是面试过程中经常被问到的问题.排序算法简单分类如下: 这些排序算法的时间复杂度等参数如下: 其中 ...

  7. 一文搞定十大经典排序算法(Java实现)

    本文总结十大经典排序算法及变形,并提供Java实现. 参考文章: 十大经典排序算法总结(Java语言实现) 快速排序算法—左右指针法,挖坑法,前后指针法,递归和非递归 快速排序及优化(三路划分等) 一 ...

  8. 十大经典排序【Java实现,手工作坊式】

    终于把排序这个硬骨头,但是又很基础的知识点,自己手撕了一遍!之前,使用Python看着算法导论的书手撕过一遍,印象不是很深刻,容易忘记!好记性不如烂笔头!多自己思考解决问题 1,交换类CAS[最简单] ...

  9. 十大经典排序算法最强总结(含JAVA代码实现)(转)

    十大经典排序算法最强总结(含JAVA代码实现)   最近几天在研究排序算法,看了很多博客,发现网上有的文章中对排序算法解释的并不是很透彻,而且有很多代码都是错误的,例如有的文章中在“桶排序”算法中对每 ...

随机推荐

  1. Golang之如何(优雅的)比较两个未知结构的json

    这是之前遇到的一道面试题,后来也确实在工作中实际遇到了.于是记录一下,如何(优雅的)比较两个未知结构的json. 假设,现在有两个简单的json文件. { "id":1, &quo ...

  2. 31-1.解决service iptables save出错

    CentOS 7.x开始,CentOS开始使用systemd服务来代替daemon,原来管理系统启动和管理系统服务的相关命令全部由systemctl命令来代替.service命令只保留下了极少部分使用 ...

  3. 免费开源的代码审计工具 Gosec 入门使用

    声明: 本教程是在自己的电脑上本地测试Gosec的效果,所以不涉及其他运行模式,如果想要了解其他模式可以关注后期文档,如果想要自定义交流自定义代码扫描规则,可以跟我交流沟通. 背景: Gosec是一个 ...

  4. Java创建线程四种方式

    1.继承Thread类 public class MyThread extends Thread { public MyThread() { } public void run() { for(int ...

  5. MySQL常用SQL语句1

    -- 创建表 CREATE TABLE USER ( -- id默认每个表都该拥有(非空 不重复) -- (id是每一行的唯一标识) -- 其他字段可能会重复,我们无法依赖其他的字段去确定某一行记录 ...

  6. PTA甲级—链表

    1032 Sharing (25分) 回顾了下链表的基本使用,这题就是判断两个链表是否有交叉点. 我最开始的做法就是用cnt[]记录每个节点的入度,发现入度为2的节点即为答案.后来发现这里忽略了两个链 ...

  7. CF-1332 F. Independent Set

    F. Independent Set 题意 一颗 n 个节点的树,求出每个\(edge-induced~subgraph\)的独立集个数之和. \(edge-induced~subgraph\)含义是 ...

  8. HDU 2176 取(m堆)石子游戏 && HDU1850 Being a Good Boy in Spring Festivaly

    HDU2176题意: m堆石子,两人轮流取.只能在1堆中取.取完者胜.先取者负输出No.先取者胜输出Yes,然后输出怎样取子. 通过 SG定理 我们可以知道每一个数的SG值,等于这个数到达不了的前面数 ...

  9. 牛客的两道dfs

    1.传送门:牛客13594-选择困难症 题意:给你k类物品,每类物品有a[i]个每个物品都有一个value,每类物品最多选一个,要求有多少种选法使得总value>m(没要求每类物品都必须选) 题 ...

  10. CodeForces - 612D 思维

    题意: 给你n个线段和一个整数k,你需要找出来所有能被任意k条线段同时覆盖的区间个数的最小值,并按从左到右的顺序输出每个区间. 题解: 对于题目输入的n个线段的左端点L,右端点R,把它们分开放在结构体 ...