一、冒泡排序

  原理: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. hashMap 底层原理+LinkedHashMap 底层原理+常见面试题

    1.源码 java1.7    hashMap 底层实现是数组+链表 java1.8 对上面进行优化  数组+链表+红黑树 2.hashmap  是怎么保存数据的. 在hashmap 中有这样一个结构 ...

  2. LC 986. Interval List Intersections

    Given two lists of closed intervals, each list of intervals is pairwise disjoint and in sorted order ...

  3. 开发软件-IntelliJ IDEA:百科

    ylbtech-开发软件-IntelliJ IDEA:百科 IDEA 全称 IntelliJ IDEA,是java语言开发的集成环境,IntelliJ在业界被公认为最好的java开发工具之一,尤其在智 ...

  4. Sql题目精选练习

    1.每日经典sql 1.1.1 根据三张关系表查询雇员中工资最高的雇员的员工姓名.工资和部门号. salary(工资表) employee(员工表) department(部门表) Sql语句: SE ...

  5. java.lang.NoClassDefFoundError: org/springframework/aop/TargetSource

    在使用Spring框架时 报错 :java.lang.NoClassDefFoundError: org/springframework/aop/TargetSource 原因:为引入spring-a ...

  6. 使用STM32F103ZET霸道主板实现LCD显示屏显示

    简单了解液晶显示屏 液晶显示屏LCD是靠背光LED发光,然后经过横竖透光,每个点电压可以改变光线的方向,总之能改变透光度0-100%,最后就是每个像素点对应红绿蓝RGB,RGB各自的亮度不同,组成的颜 ...

  7. 最新 4399java校招面经 (含整理过的面试题大全)

    从6月到10月,经过4个月努力和坚持,自己有幸拿到了网易雷火.京东.去哪儿.4399等10家互联网公司的校招Offer,因为某些自身原因最终选择了4399.6.7月主要是做系统复习.项目复盘.Leet ...

  8. spring的控制器如何跳转到指定的视图

    1.控制器代码 2.跳转代码 return "greeting"; 引号内为跳转的页面,默认不需要加html

  9. Vue父子组件传值$parent , ref,$refs,props大总结

    子组件: <template> <div class="child"> <slot name='meiyong'></slot> & ...

  10. @KafkaListener和@KafkaListeners的使用

    2. consumer 使用了@KafkaListener注解. 2.1. pom.xml 引入以下依赖 <dependency> <groupId>org.springfra ...