一:冒泡排序

1. 原理

a. 从头开始比较相邻的两个待排序元素,如果前面元素大于后面元素,就将二个元素位置互换

b. 这样对序列的第0个元素到n-1个元素进行一次遍历后,最大的一个元素就“沉”到序列的最后位置(第n-1个位置,n为待排序元素个数)

c.排除此次排序最后面的那个元素(n=n-1),继续对剩余序列重复前面两步

d. 当(n= n-1)=0时,排序完成

2. 具体实现

以如下待排序序列为例:

到此,第一次冒泡完成,最大值7冒泡到最后面。

然后继续对除最后元素(7)外的序列进行冒泡排序。具体实现如下:

/**
* 冒泡排序
* @param {Array} arr - 整型数组
* @returns {Array} ret - 排好序的数组
*/ function bubbleSort(arr) {
var n = arr.length,
i = 0,
temp; while(--n) { while (i < n) { // 如果前一个数大于后一个数,则互换位置
if(arr[i] > arr[i+1]) {
temp = arr[i];
arr[i] = arr[i+1];
arr[i+1] = temp;
} i++;
} // 每次冒泡完成后,将i复位
i = 0;
} return arr;
} // 基于qunit的测试
test('bubble-sort', function () {
var arr1 = [6,2,4,3];
var arr2 = [28,13,4,19,10];
var arr3 = [2,3,2,4,2,5]; propEqual(bubbleSort(arr1), [2,3,4,6]);
propEqual(bubbleSort(arr2), [4,10,13,19,28]);
propEqual(bubbleSort(arr3), [2,2,2,3,4,5]);
});

二:选择排序

1. 原理

a. 首先在待排序序列中找到最小元素,放入储存有序序列中。同时从待排序序列中删除这个元素

b. 继续从未排序序列中找到最小元素,然后a步中的有序列序列中

c. 以此类推,直到待排序序列元素个数为0

2.  具体实现:

/**
* 选择排序
* @param {Array} arr
* @returns {Array} ret
*/
function selectionSort(arr) {
var ret = [],
min,
i; while(arr.length) { // TODO 应该自己实现一个求数组中的最小值方法
min = Math.min.apply(null, arr); ret.push(min); // 从待排序数组中删除这个元素
arr.splice(arr.indexOf(min), 1); } return ret;
} // qunit
test('selection-sort', function () {
var arr1 = [1,5,3,6,4,2];
var arr2 = [1,5,4,6,4,2]; propEqual(selectionSort(arr1), [1,2,3,4,5,6]);
propEqual(selectionSort(arr2), [1,2,4,4,5,6]); });

三: 插入排序

1. 排序原理:

a. 从待排序序列第0个元素开始排序,该元素可以认为已经是有序的

b. 取出下一个元素,在已经排序的元素序列中从后向左遍历

c. 如果已排序元素大于新元素,将该元素移到下一位置

d. 重复步骤c,直到找到一个已排序的元素,此元素不大于新元素;或者元素位于有有序序列开始位置

e. 将新元素插入到此元素后面

f. 重复步骤b~e,直接待排元素个数为0

2. 具体实现

/**
* 插入排序
* @param {Array} arr
* @returns {Array} ret
*/
function insertionSort(arr) { // 从1开始,因为一个元素的序列,始终是有序的
for(var i = 1, j; i < arr.length; i++) { j = i; // 保存待排序元素
v= arr[j]; // 如果有序序列中的元素大于待插入的元素,则有序列序列中的元素向后移动一个位置
// 向后移到一个位置,会覆盖待排序的元素,但我们前面有保存待排序元素,所以待排序元素不会丢失
// 同时,也留出一个位置,以插入待排序元素
// 直到找一个已经排序的元素,其不大于待排序元素,将待排序元素插入到这里。
// 如果遍历到有序序列的开始位置,也不存在一个元素不大于待排序元素,则将待排序元素插入到已经排序序列的开始 while(arr[j-1] > v) {
arr[j] = arr[j-1];
j--; if(j === 0) {
break;
}
} arr[j] = v;
} return arr;
} // qunit
test('insertion-sort', function () {
var arr1 = [1,5,3,6,4,2];
var arr2 = [1,5,4,6,4,2]; propEqual(insertionSort(arr1), [1,2,3,4,5,6]);
propEqual(insertionSort(arr2), [1,2,4,4,5,6]); });

四:希尔排序

1.  排序原理:

a. 设定一个间距d,将待排序序列分组

b. 对分组使用插入排序

c. 改变d, 再次分组

d. 再次对上面的分组使用插入排序

e. 重复上面的步骤,直至d为1,并进行最后一次插入排序,得到排好序的序列

2. 具体实现

希尔排序过程中,涉及到选择一组间距序列,这个序列叫叫希尔增量。希尔增量的奥妙以后有时间再研究。

/**
* 希尔排序
* @param {Array} arr
* @returns {Array}
*/
function shellSort(arr) { // 动态取得一个希尔增量 var N = arr.length;
var h = 1; var i, j, v; // 产生希尔增量序列第一个值
while (h < N / 3) {
h = 3 * h + 1; // ①
} // 对分组使用插入排序,同时改变希尔增量值,直到其为1,并进行最后一次插入排序,得到有序序列
// 第一次插入排序,都是可以将待排序序列排成有序序列的
// 不停运用插入排序,其实是减少了元素在排序过程中移动的次数
while (h >= 1) {
for (i = 1; i < arr.length; i++) { j = i;
v = arr[j]; while (j > 0 && arr[j - 1] > v) {
arr[j] = arr[j - 1];
j--;
} arr[j] = v;
} h = (h - 1) / 3; // 从①可以保证,肯定能除尽的
} return arr;
} // qunit
test('shell-sort', function () {
var arr1 = [1,5,3,6,4,2,22,34,11,12,45];
var arr2 = [1,5,4,6,4,2]; propEqual(shellSort(arr1), [1,2,3,4,5,6,11,12,22,34,45]);
propEqual(shellSort(arr2), [1,2,4,4,5,6]); });

五. 归并排序

1. 排序原理:

归并排序主要分两步:

a. 分组

对待排序序列按二分法分成两个小序列,并一直递归下去,直到序列长度为1(长度为1 的序列是有序的)

b. 合并

将排好序的数组合并成有序数列,最后得到排序结果

2. 具体实现

// 归并排序
function mergetSort(arr) { if(arr.length === 1) {
return arr;
} var leftArr = arr.slice(0, Math.floor(arr.length / 2));
var rightArr = arr.slice(leftArr.length); // 递归
return merge(mergetSort(leftArr), mergetSort(rightArr)); // 合并有序序列
function merge(arrLeft, arrRight) { var indexLeft = 0,
indexRight = 0,
sl = arrLeft.length,
sr = arrRight.length,
ret = []; while(true) {
if(indexLeft < sl && indexRight < sr) {
if(arrLeft[indexLeft] < arrRight[indexRight]) {
ret.push(arrLeft[indexLeft]);
indexLeft++;
} else {
ret.push(arrRight[indexRight]);
indexRight++;
}
} else {
if(indexLeft < indexRight) {
ret = ret.concat(arrLeft.slice(indexLeft));
} else {
ret = ret.concat(arrRight.slice(indexRight));
}
break;
}
} return ret;
} } // qunit
test('merge-sort', function () {
var arr1 = [28,13,4,19,10];
var arr2 = [1,5,4,6,4,2]; propEqual(mergetSort(arr1), [4,10,13,19,28]);
propEqual(mergetSort(arr2), [1,2,4,4,5,6]);
});

六: 快速排序

1. 排序原理

a. 从序列中挑出一个元素,称为 "基准"(pivot),

b. 重新排序序列,所有元素比基准值小的元素摆放在基准前面,所有元素比基准值大的摆在基准后面

c. 把新得到的序列再通过上面的方法排序。当序列长度为1或0时结束递归

2. 具体实现

// 快速排序
function quickSort(arr) {
var pivot = arr[0];
var i = 1;
var leftArr= [],
rightArr = []; if(arr.length === 0) {
return [];
} if(arr.length === 1) {
return arr;
} for(; i < arr.length; i++) {
if(arr[i] < pivot) {
leftArr.push(arr[i]);
} else {
rightArr.push(arr[i]);
}
} return quickSort(leftArr).concat(pivot, quickSort(rightArr));
} // qunit
test('quick-sort', function () {
var arr1 = [6,2,4,3];
var arr2 = [28,13,4,19,10];
var arr3 = [4,1,7,3,5,2,6]; propEqual((quickSort(arr1)), [2,3,4,6]);
propEqual(quickSort(arr2), [4,10,13,19,28]);
propEqual(quickSort(arr3), [1,2,3,4,5,6,7]);
});

小结:

本文把常见的排序算法(冒泡,选择,插入,希尔,归并,快速排序)基于JS实现了一遍,练习一下算法,还是有助于提高编程思维的。比如求一个数组的最大值。我们知道可以这样:

var max = Math.min.applu(null, arr)

但是浏览器内部是怎么实现的呢,又或者假设浏览器没提供这个方法,我们自己怎么做呢?其实通过一次向左冒泡就可以得到最小值:

function getMinValue(arr) {
var i = arr.length, j; j = i; while(--j) {
if(arr[j - 1] > arr[j]) {
arr[j - 1] = [arr[j - 1], arr[j]];
arr[j] = arr[j - 1][0];
arr[j- 1] = arr[j - 1][1];
}
} // 返回最小值
return arr[0];
}

常见排序算法基于JS的实现的更多相关文章

  1. 常见排序算法(JS版)

    常见排序算法(JS版)包括: 内置排序,冒泡排序,选择排序,插入排序,希尔排序,快速排序(递归 & 堆栈),归并排序,堆排序,以及分析每种排序算法的执行时间. index.html <! ...

  2. 常见排序算法原理及JS代码实现

    目录 数组 sort() 方法 冒泡排序 选择排序 插入排序 希尔排序 归并排序 堆排序 快速排序 创建时间:2020-08-07 本文只是将作者学习的过程以及算法理解进行简单的分享,提供多一个角度的 ...

  3. JS常见排序算法

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  4. JavaScript版几种常见排序算法

    今天发现一篇文章讲“JavaScript版几种常见排序算法”,看着不错,推荐一下原文:http://www.w3cfuns.com/blog-5456021-5404137.html 算法描述: * ...

  5. python常见排序算法解析

    python——常见排序算法解析   算法是程序员的灵魂. 下面的博文是我整理的感觉还不错的算法实现 原理的理解是最重要的,我会常回来看看,并坚持每天刷leetcode 本篇主要实现九(八)大排序算法 ...

  6. python——常见排序算法解析

    算法是程序员的灵魂. 下面的博文是我整理的感觉还不错的算法实现 原理的理解是最重要的,我会常回来看看,并坚持每天刷leetcode 本篇主要实现九(八)大排序算法,分别是冒泡排序,插入排序,选择排序, ...

  7. 常见排序算法总结 -- java实现

    常见排序算法总结 -- java实现 排序算法可以分为两大类: 非线性时间比较类排序:通过比较来决定元素间的相对次序,由于其时间复杂度不能突破O(nlogn),因此称为非线性时间比较类排序. 线性时间 ...

  8. 常见排序算法题(java版)

    常见排序算法题(java版) //插入排序:   package org.rut.util.algorithm.support;   import org.rut.util.algorithm.Sor ...

  9. [算法] 常见排序算法总结(C语言版)

    常见排序算法总结 本文对比较常用且比较高效的排序算法进行了总结和解析,并贴出了比较精简的实现代码,包括选择排序.插入排序.归并排序.希尔排序.快速排序等.算法性能比较如下图所示: 1 冒泡排序 基本原 ...

随机推荐

  1. 540A: Combination Lock

    题目链接:http://codeforces.com/problemset/problem/540/A 题意: 输入的两个长度一样的数,求对应位置的某位数到下一个数需要最小的步长,每次只能先前或先后走 ...

  2. [C#] 區分 abstract、virtual、override 和 new

    abstract.virtual.override和new是在類別的繼承關係中常用的四個修飾方法的關鍵字,在此略作總結. 1. 常用的中文名稱: n   abstract => 抽象方法. n  ...

  3. AcmeAir安装AI探针--SaaS版

    一.安装SaaS版AI探针准备工作: 1.准备好可用的docker版AcmeAir应用 2.在SaaS官网tpm.oneapm.com上已注册可用的账号 3.登录tpm.oneapm.com,点击选择 ...

  4. Outlook与Hotmail的设置

    最近研究邮件备份,首先要使用客户端下载邮件,碰到不少问题:1. HOTMAIL GMAIL SINA的POP/IMAP默认居然都是关闭的,必须改成开放才行. GMAIL改成开放以后还是没有成功,好像还 ...

  5. WordPress主题制作教程2:导航菜单制作

    实现自定义菜单,需要用到的函数是wp_nav_menu(); 在主题目录下的functions.php的 <?php ….. ?> 之间,添加以下菜单注册代码,这样你就可以在主题文件中使用 ...

  6. [iOS]iPhone推送原理

    推送原理,先上图 说一下原理吧, 由App向iOS设备发送一个注册通知 iOS向APNs远程推送服务器发送App的Bundle Id和设备的UDID APNs根据设备的UDID和App的Bundle ...

  7. oracle11g 远程登录数据库

    oracle11g 远程登录数据库比以往的任何版本都要简单,什么也不用做 1.OEM登录 在浏览器中直接输入,远程数据库的OEM网址,当然要把localhost或者主机名改成ip地址   https: ...

  8. ES6入门之set和map

    Set ES6提供了新的数据结构Set.它类似于数组,但是成员的值都是唯一的,没有重复的值. Set函数可以接受一个数组(或类似数组的对象)作为参数,用来初始化. // 例一 var set = ne ...

  9. google protobuf使用

    下载的是github上的:https://github.com/google/protobuf If you get the source from github, you need to gener ...

  10. 【转】HashMap的工作原理

    很好的文章,推荐Java的一个好网站:ImportNew HashMap的工作原理是近年来常见的Java面试题.几乎每个Java程序员都知道HashMap,都知道哪里要用HashMap,知道Hasht ...