1.冒泡排序(Bubble Sort)

冒泡排序是一种简单的排序算法。它重复地遍历过要排序的数列,每次比较两个元素,如果它们的顺序不符合预期,就把它们的位置交换过来。遍历数列的工作是重复地进行直到没有再需要交换。因为每遍历数列一次,就有一个元素“浮”到数列的顶端,故此叫做“冒泡排序”。

简要步骤

  1. 比较相邻的元素。如果第一个比第二个大,就交换它们两个;
  2. 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对,这样在最后的元素应该会是最大的数;
  3. 针对所有的元素重复以上的步骤,除了最后一个;
  4. 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。

具体实现

Array.prototype.bubble_sort = function() {var i, j, tempfor (i = 0; i < this.length - 1; i++)for (j = 0; j < this.length - 1 - i; j++)if (this[j] > this[j + 1]) {temp = this[j]this[j] = this[j + 1]this[j + 1] = temp}return this
}

改进冒泡排序:设置一标志性变量 pos,用于记录每趟排序中最后一次进行交换的位置。由于 pos 位置之后的记录均已交换到位,故在进行下一趟排序时只要扫描到 pos 位置即可。

Array.prototype.bubble_sort_improve = function() {var i = this.length - 1 //初始时,最后位置保持不变while (i > 0) {var pos = 0 //每趟开始时,无记录交换for (var j = 0; j < i; j++)if (this[j] > this[j + 1]) {pos = j //记录交换的位置var tmp = this[j]this[j] = this[j + 1]this[j + 1] = tmp}i = pos //为下一趟排序作准备}return this
}

算法分析

  • 最佳情况:T(n) = O(n)
  • 最差情况:T(n) = O(n2)
  • 平均情况:T(n) = O(n2)

2.选择排序(Selection Sort)

是一种简单直观的排序算法。它的工作原理如下。首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。

简要步骤

  1. 初始状态:无序区为 R[1..n],有序区为空;
  2. 第 i 趟排序(i=1,2,3...n-1)开始时,当前有序区和无序区分别为 R[1..i-1]和 R(i..n)。该趟排序从当前无序区中-选出关键字最小的记录 R[k],将它与无序区的第 1 个记录 R 交换,使 R[1..i]和 R[i+1..n)分别变为记录个数增加 1 个的新有序区和记录个数减少 1 个的新无序区;
  3. n-1 趟结束,数组有序化了。

具体实现

Array.prototype.selection_sort = function() {var i, j, minvar tempfor (i = 0; i < this.length - 1; i++) {min = ifor (j = i + 1; j < this.length; j++) if (this[min] > this[j]) min = jtemp = this[min]this[min] = this[i]this[i] = temp}
}

算法分析

  • 最佳情况:T(n) = O(n2)
  • 最差情况:T(n) = O(n2)
  • 平均情况:T(n) = O(n2)

3.插入排序(Insertion Sort)

通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。插入排序在实现上,通常采用 in-place 排序(即只需用到 {displaystyle O(1)} {displaystyle O(1)}的额外空间的排序),因而在从后向前扫描过程中,需要反复把已排序元素逐步向后挪位,为最新元素提供插入空间。

简要步骤

  1. 从第一个元素开始,该元素可以认为已经被排序
  2. 取出下一个元素,在已经排序的元素序列中从后向前扫描
  3. 如果该元素(已排序)大于新元素,将该元素移到下一位置
  4. 重复步骤 3,直到找到已排序的元素小于或者等于新元素的位置
  5. 将新元素插入到该位置后
  6. 重复步骤 2~5

具体实现

Array.prototype.insertion_sort = function() {var i, jfor (i = 1; i < this.length; i++) {for (j = 0; j < i; j++) {if (this[j] > this[i]) {this.splice(j, 0, this[i])this.splice(i + 1, 1)}}}return this
}

算法分析

  • 最佳情况:输入数组按升序排列。T(n) = O(n)
  • 最坏情况:输入数组按降序排列。T(n) = O(n2)
  • 平均情况:T(n) = O(n2)

4.希尔排序(Shell Sort)

插入排序在对几乎已经排好序的数据操作时,效率高,即可以达到线性排序的效率。但插入排序一般来说是低效的,因为插入排序每次只能将数据移动一位。

简要步骤

  1. 选择一个增量序列 t1,t2,…,tk,其中 ti>tj,tk=1;
  2. 按增量序列个数 k,对序列进行 k 趟排序;
  3. 每趟排序,根据对应的增量 ti,将待排序列分割成若干长度为 m 的子序列,分别对各子表进行直接插入排序。仅增量因子为 1 时,整个序列作为一个表来处理,表长度即为整个序列的长度。

具体实现

Array.prototype.shell_sort = function() {var gap, i, jvar tempfor (gap = this.length >> 1; gap > 0; gap >>= 1)for (i = gap; i < this.length; i++) {temp = this[i]for (j = i - gap; j >= 0 && this[j] > temp; j -= gap)this[j + gap] = this[j]this[j + gap] = temp}
}

算法分析

  • 最佳情况:T(n) = O(nlog2 n)
  • 最坏情况:T(n) = O(nlog2 n)
  • 平均情况:T(n) =O(nlog n)

5.归并排序(Merge Sort)

归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。归并排序是一种稳定的排序方法。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为 2-路归并。

简要步骤

  1. 将序列每相邻两个数字进行归并操作,形成ceil(n/2)个序列,排序后每个序列包含两/一个元素
  2. 若此时序列数不是 1 个则将上述序列再次归并,形成 ceil(n/4)个序列,每个序列包含四/三个元素
  3. 重复步骤 2,直到所有元素排序完毕,即序列数为 1

具体实现

Array.prototype.merge_sort = function() {var merge = function(left, right) {var final = []while (left.length && right.length)final.push(left[0] <= right[0] ? left.shift() : right.shift())return final.concat(left.concat(right))}var len = this.lengthif (len < 2) return thisvar mid = len / 2return merge(this.slice(0, parseInt(mid)).merge_sort(),this.slice(parseInt(mid)).merge_sort())
}

算法分析

  • 最佳情况:T(n) = O(n)
  • 最差情况:T(n) = O(nlogn)
  • 平均情况:T(n) = O(nlogn)

6.快速排序(Quick Sort)

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

简要步骤

  1. 从数列中挑出一个元素,称为"基准"(pivot),
  2. 重新排序数列,所有比基准值小的元素摆放在基准前面,所有比基准值大的元素摆在基准后面(相同的数可以到任何一边)。在这个分区结束之后,该基准就处于数列的中间位置。这个称为分区(partition)操作。
  3. 递归地(recursively)把小于基准值元素的子数列和大于基准值元素的子数列排序。

具体实现

Array.prototype.quick_sort = function() {var len = this.lengthif (len <= 1) return this.slice(0)var left = []var right = []var mid = [this[0]]for (var i = 1; i < len; i++)if (this[i] < mid[0]) left.push(this[i])else right.push(this[i])return left.quick_sort().concat(mid.concat(right.quick_sort()))
}

算法分析

  • 最佳情况:T(n) = O(nlogn)
  • 最差情况:T(n) = O(n2)
  • 平均情况:T(n) = O(nlogn

7.堆排序(Heap Sort)

堆排序是指利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。

简要步骤

  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,则整个排序过程完成。

具体实现

Array.prototype.heap_sort = function() {var arr = this.slice(0)function swap(i, j) {var tmp = arr[i]arr[i] = arr[j]arr[j] = tmp}function max_heapify(start, end) {//建立父节点指标和子节点指标var dad = startvar son = dad * 2 + 1if (son >= end)//若子节点指标超过范围直接跳出函數returnif (son + 1 < end && arr[son] < arr[son + 1])//先比较两个子节点大小,选择最大的son++if (arr[dad] <= arr[son]) {//如果父节点小于子节点时,交换父子内容再继续子节点和孙节点比较swap(dad, son)max_heapify(son, end)}}var len = arr.length//初始化,i从最后一个父节点开始调整for (var i = Math.floor(len / 2) - 1; i >= 0; i--) max_heapify(i, len)//先将第一个元素和已排好元素前一位做交换,再重新调整,直到排序完毕for (var i = len - 1; i > 0; i--) {swap(0, i)max_heapify(0, i)}return arr
}

算法分析

  • 最佳情况:T(n) = O(nlogn)
  • 最差情况:T(n) = O(nlogn)
  • 平均情况:T(n) = O(nlogn)

8.计数排序(Counting Sort)

计数排序是一种稳定的线性时间排序算法。计数排序使用一个额外的数组 C,其中第 i 个元素是待排序数组 A 中值等于 i 的元素的个数。然后根据数组 C 来将 A 中的元素排到正确的位置。

简要步骤

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

具体实现

Array.prototype.counting_sort = function() {var len = this.length,B = [],C = [],min = (max = this[0])for (var i = 0; i < len; i++) {min = min <= this[i] ? min : this[i]max = max >= this[i] ? max : this[i]C[this[i]] = C[this[i]] ? C[this[i]] + 1 : 1}for (var j = min; j < max; j++) {C[j + 1] = (C[j + 1] || 0) + (C[j] || 0)}for (var k = len - 1; k >= 0; k--) {B[C[this[k]] - 1] = this[k]C[this[k]]--}return B
}

算法分析

  • 最佳情况:T(n) = O(n+k)
  • 最差情况:T(n) = O(n+k)
  • 平均情况:T(n) = O(n+k)

9.桶排序(Bucket Sort)

桶排序或所谓的箱排序,是一个排序算法,工作的原理是将数组分到有限数量的桶里。每个桶再个别排序(有可能再使用别的排序算法或是以递归方式继续使用桶排序进行排序)。

简要步骤

  1. 设置一个定量的数组当作空桶子。
  2. 寻访序列,并且把项目一个一个放到对应的桶子去。
  3. 对每个不是空的桶子进行排序。
  4. 从不是空的桶子里把项目再放回原来的序列中。

具体实现

Array.prototype.bucket_sort = function(num) {if (this.length <= 1) {return this}var len = this.length,buckets = [],result = [],min = (max = this[0]),regex = '/^[1-9]+[0-9]*$/',space,n = 0num = num || (num > 1 && regex.test(num) ? num : 10)for (var i = 1; i < len; i++) {min = min <= this[i] ? min : this[i]max = max >= this[i] ? max : this[i]}space = (max - min + 1) / numfor (var j = 0; j < len; j++) {var index = Math.floor((this[j] - min) / space)if (buckets[index]) {//  非空桶,插入排序var k = buckets[index].length - 1while (k >= 0 && buckets[index][k] > this[j]) {buckets[index][k + 1] = buckets[index][k]k--}buckets[index][k + 1] = this[j]} else {//空桶,初始化buckets[index] = []buckets[index].push(this[j])}}while (n < num) {result = result.concat(buckets[n])n++}return result
}

算法分析

  • 最佳情况:T(n) = O(n+k)
  • 最差情况:T(n) = O(n+k)
  • 平均情况:T(n) = O(n2)

10.基数排序(Radix Sort)

基数排序是一种非比较型整数排序算法,其原理是将整数按位数切割成不同的数字,然后按每个位数分别比较。由于整数也可以表达字符串(比如名字或日期)和特定格式的浮点数,所以基数排序也不是只能使用于整数。将所有待比较数值(正整数)统一为同样的数位长度,数位较短的数前面补零。然后,从最低位开始,依次进行一次排序。这样从最低位排序一直到最高位排序完成以后,数列就变成一个有序序列。

简要步骤

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

具体实现

Array.prototype.radix_sort = function(maxDigit) {var mod = 10var dev = 1var counter = []console.time('基数排序耗时')for (var i = 0; i < maxDigit; i++, dev *= 10, mod *= 10) {for (var j = 0; j < this.length; j++) {var bucket = parseInt((this[j] % mod) / dev)if (counter[bucket] == null) {counter[bucket] = []}counter[bucket].push(this[j])}var pos = 0for (var j = 0; j < counter.length; j++) {var value = nullif (counter[j] != null) {while ((value = counter[j].shift()) != null) {this[pos++] = value}}}}console.timeEnd('基数排序耗时')return this
}

算法分析

  • 最佳情况:T(n) = O(n * k)
  • 最差情况:T(n) = O(n * k)
  • 平均情况:T(n) = O(n * k)

基数排序有两种方法:

MSD 从高位开始进行排序 LSD 从低位开始进行排序

基数排序 vs 计数排序 vs 桶排序 这三种排序算法都利用了桶的概念,但对桶的使用方法上有明显差异:

  • 基数排序:根据键值的每位数字来分配桶
  • 计数排序:每个桶只存储单一键值
  • 桶排序:每个桶存储一定范围的数值

shell sort 最后一列排序_算法实现系列(1)—— 排序算法相关推荐

  1. python中用def实现自动排序_用 python 实现各种排序算法

    常见集中排序的算法 归并排序 归并排序也称合并排序,是分治法的典型应用.分治思想是将每个问题分解成个个小问题,将每个小问题解决,然后合并. 具体的归并排序就是,将一组无序数按n/2递归分解成只有一个元 ...

  2. 使用qsort对不连续的内存数据排序_常见的内排序和外排序算法

    常见的内排序算法 所谓的内排序是指所有的数据已经读入内存,在内存中进行排序的算法.排序过程中不需要对磁盘进行读写.同时,内排序也一般假定所有用到的辅助空间也可以直接存在于内存中.与之对应地,另一类排序 ...

  3. javascript排序_鸡尾酒在JavaScript中排序

    javascript排序 Just want the code? Scroll all the way down for two versions of the code: 只需要代码? 一直向下滚动 ...

  4. 数据结构python学生成绩排序_科学网—数据结构之排序一(python实现) - 郗强的博文...

    本文介绍三种简单的排序算法,包括选择排序.冒泡排序和插入排序.同样每个python的排序函数都是在一个整数列表上进行操作的. 一.交换函数 在每个排序函数中都会使用一个swap函数来交换列表中两个元素 ...

  5. mysql查询后从高到低排序_[MySQL基础]三、排序查询

    排序查询 语法: SELECT 查询列表 FROM 表 [WHERE 筛选条件] ORDER BY 排序列表 [ASC|DESC]; #[ ]中的内容表示可选 特点:asc代表的是升序,desc代表的 ...

  6. mysql电商产品排序_电商平台商品排序

    电商平台的商品排序一般由四类元素影响: 第一类:按照百分比计算,如商品转化率.好评率.回购率: 第二类:按照状态计算,如上下架: 第三类:按照数值计算,如销量和人气是数值的积累: 第四类:按照配比计算 ...

  7. shell sort 最后一列排序_十个必知的排序算法|Python实例系列[1]

    实例内容: 十个必知的排序算法具体代码,并简略的得知每种算法对于不同长度数列的排序时间 十大排序: 1.冒泡排序2.选择排序3.插入排序4.希尔排序5.归并排序6.快速排序7.堆排序8.计数排序9.桶 ...

  8. list 排序_十个必知的排序算法|Python实例系列

    十大排序: 1.冒泡排序2.选择排序3.插入排序4.希尔排序5.归并排序6.快速排序7.堆排序8.计数排序9.桶排序10.基数排序 完整代码和注释如下 # -*- coding: UTF-8 -*-# ...

  9. c++用向量给句子排序_用C ++对向量排序

    c++用向量给句子排序 介绍 (Introduction) In this tutorial, we are going to focus on Sorting a Vector in C++. 在本 ...

最新文章

  1. mysql 软件导出导入数据_MySQL 之 导出导入数据
  2. 研发团队资源成本优化实践
  3. 如何修改xd.properties文件中对象存储文件信息_对块存储、文件存储、对象存储的认识总结...
  4. .net工程师至少要懂的东西
  5. flume 中的 hdfs sink round 和roll
  6. Django:ORM基本操作-CRUD,管理器对象objects,----->聚合查询、原生数据库操作
  7. 用for循环打印出九九乘法表
  8. python pdf转word
  9. 苹果手机连接电脑服务器传文件,实用!三种iPhone与Windows电脑互传文件操作技巧,...
  10. MPI + OpenMP实现快速排序
  11. JAVA 仿XP画图板的总结
  12. [报错]CXF动态客户端报错:No operation was found with the name
  13. MySQL 报OperationalError: (1130, “XX‘ is not allowed to connect to this MySQL server“)的正确解决方法
  14. activemq如何保证消息按顺序消费
  15. 正本清源:为什么区块链是一次新的信息化革命
  16. 新手程序员快速升职项目经理(程序员小故事1)
  17. jquery的运行机制
  18. Excel函数-日期相关函数(计算间隔日期)
  19. ## **#安装数据库SQL Server 2008R2 时,提示安装或配置microsoft.net framework 3.5 sp1**
  20. SARscape SBAS-InSAR形变处理流程(哨兵1)

热门文章

  1. Mac 16进制编辑器Hex Friend
  2. 高中数学的复数:y=a + bi
  3. 成功转型机器学习,多年的经验分享
  4. Vue之脚手架第一个项目
  5. 视频编解码(五):解码器驱动代码理解
  6. java children_java构建树形列表(带children属性)
  7. git学习(九)跨团队协作-非团队成员参与git项目开发
  8. 【无标题】排序算法(C语言)
  9. cesium 模型绕点飞行一周
  10. seafile Windows MySQL_seafile4.3.1 + windows 2012 server +mysql 部署记录(3)