首先生成一个数字数组:

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. Flink-v1.12官方网站翻译-P020-Builtin Watermark Generators

    内置水印生成器 正如在Generating Watermarks一文中所描述的,Flink提供了抽象,允许程序员分配自己的时间戳和发射自己的水印.更具体地说,可以通过实现WatermarkGenera ...

  2. 90% 的 Java 程序员都说不上来的为何 Java 代码越执行越快(2)- TLAB预热

    经常听到 Java 性能不如 C/C++ 的言论,也经常听说 Java 程序需要预热,那么其中主要原因是啥呢? 面试的时候谈到 JVM,也有很多面试官喜欢问,为啥 Java 程序越执行越快呢? 一般人 ...

  3. OLAP、OLTP的介绍和比较(转载)

    OLTP与OLAP的介绍 数据处理大致可以分成两大类:联机事务处理OLTP(on-line transaction processing).联机分析处理OLAP(On-Line Analytical ...

  4. windows 系统下安装kibana和sense

    目前最新版本已经不需要安装sense了,而是使用Dev Tools工具: 下面进行下载和安装kibana. 点击下载:https://artifacts.elastic.co/downloads/ki ...

  5. Selenium+Python之下拉菜单的定位

    1.通过selenium.webdriver.support.ui的Select进行定位 下拉菜单如下图: 定位代码(选择Male): from selenium.webdriver.support. ...

  6. EF Core数据访问入门

    重要概念 Entity Framework (EF) Core 是轻量化.可扩展.开源和跨平台的数据访问技术,它还是一 种对象关系映射器 (ORM),它使 .NET 开发人员能够使用面向对象的思想处理 ...

  7. CF1462-C. Unique Number

    题意: 给出一个数字x,让你找出一个由1到9这九个数字组成的数字,这个数字的每一位加起来等于x,并且1到9每个数字只能出现一次.若能找到这样的数字,输出这其中最小的一个,否则输出-1. 思路: 利用二 ...

  8. Excel添加超链接

    using Microsoft.Office.Interop.Excel; Worksheet sheet; public void AddLink(int row, int col, string ...

  9. FZU2105 Digits Count(按位建线段树)题解

    题意: 给出区间与.或.异或\(x\)操作,还有询问区间和. 思路: 因为数比较小,我们给每一位建线段树,这样每次只要更新对应位的答案. 与\(0\)和或\(1\)相当于重置区间,异或\(1\)相当于 ...

  10. Bootstrap巨幕

    这是一个轻量.灵活的组件,它能延伸至整个浏览器视口来展示网站上的关键内容. jumbotron修饰 <div class="jumbotron"> <h1> ...