说明:
- 排序算法的实现均为正序(从小到大)
- 实现的语言为Typescript
文章目录
0 算法概述
0.1 算法分类
十种常见排序算法可以分为两大类:
- 比较类排序:通过比较来决定元素间的相对次序,由于其时间复杂度不能突破O(nlogn),因此也称为非线性时间比较类排序。
- 非比较类排序:不通过比较来决定元素间的相对次序,它可以突破基于比较排序的时间下界,以线性时间运行,因此也称为线性时间非比较类排序。
0.2 相关概念
- 稳定:如果a原本在b前面,而a=b,排序之后a仍然在b的前面。
- 不稳定:如果a原本在b的前面,而a=b,排序之后 a 可能会出现在 b 的后面。
- 时间复杂度:对排序数据的总的操作次数。反映当n变化时,操作次数呈现什么规律。
- 空间复杂度:是指算法在计算机
0.3 算法复杂度
排序 | 时间复杂度(平局) | 时间复杂度(最坏) | 时间复杂度(最好) | 空间复杂度 | 稳定性 |
---|---|---|---|---|---|
冒泡 | O( n² ) | O( n² ) | O( n ) | O( 1 ) | 稳定 |
选择 | O( n² ) | O( n² ) | O( n² ) | O( 1 ) | 不稳定 |
插入 | O( n² ) | O( n² ) | O( n ) | O( 1 ) | 稳定 |
希尔 | O( n1.3 ) | O( n² ) | O( n ) | O( 1 ) | 不稳定 |
归并 | O( nlog2n ) | O( nlog2n ) | O( nlog2n ) | O( nlog2n ) | 稳定 |
快速 | O( nlog2n ) | O( n² ) | O( nlog2n ) | O( 1 ) | 不稳定 |
堆 | O( nlog2n ) | O( nlog2n ) | O( nlog2n ) | O( 1 ) | 不稳定 |
计数 | O( n + k ) | O( n + k ) | O( n + k ) | O( n + k ) | 稳定 |
桶 | O( n + k ) | O( n² ) | O( n ) | O( n + k ) | 稳定 |
基数 | O( n * k ) | O( n * k ) | O( n * k ) | O( n + k ) | 稳定 |
1 冒泡排序 ( Bubble Sort )
冒泡排序是一种简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端
1.1 算法描述
- 比较相邻的元素,如果第一个比第二个大,则交换位置
- 对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数
- 针对所有的元素重复以上的步骤,除了最后一个(已经确定的元素)
- 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较
1.2 代码实现
function BubbleSort ( arr: any[], len: number = arr.length ){
let i = 0, j = 0;
for ( ; i < len; i++ ) {
for ( ; j < len - i - 1; j++ ) {
if ( arr[ j ] > arr[ j + 1 ] ) continue;
[ arr[ j ], arr[ j + 1 ] ] = [ arr[ j + 1 ], arr[ j ] ];
}
}
}
1.3 算法分析
排序 | 时间复杂度(平局) | 时间复杂度(最坏) | 时间复杂度(最好) | 空间复杂度 | 稳定性 |
---|---|---|---|---|---|
冒泡 | O( n² ) | O( n² ) | O( n ) | O( 1 ) | 稳定 |
2 选择排序 ( Selection Sort )
在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕
2.1 算法描述
- 从待排序序列中,找到关键字最小的元素
- 如果最小元素不是待排序序列的第一个元素,将其和第一个元素互换
- 从余下的 N - 1 个元素中,找出关键字最小的元素,重复(1)、(2)步,直到排序结束
2.2 代码实现
function SelectSort( arr: any[], len: number = arr.length):void {
let minIndex = -1;
let i = 0, j = 0;
for( ; i < len - 1; i++ ) {
minIndex = i;
for( j = i ; j < len ; j++ ) {
if( arr[ minIndex] > arr[ j ] )
minIndex = j;
}
[ arr[ i ], arr[ minIndex ] ] = [ arr[ minIndex],arr[ i ] ];
}
}
2.3 算法分析
排序 | 时间复杂度(平局) | 时间复杂度(最坏) | 时间复杂度(最好) | 空间复杂度 | 稳定性 |
---|---|---|---|---|---|
选择 | O( n² ) | O( n² ) | O( n² ) | O( 1 ) | 不稳定 |
- 选择排序算法中的比较次数与元素的初始排列无关,因为总是必须比较后面的待排序元素已确定当前元素具有最小的排序码
- 素的移动次数与元素的初始排列有关,因为当元素是从小到大排序时,移动次数是0;而最坏情况下,每次都要进行交换,移动次数是 3*(n-1)
- 表现最稳定(指时间复杂度)的排序算法之一,因为无论什么数据进去都是O(n2)的时间复杂度,所以用到它的时候,数据规模越小越好
- 唯一的好处可能就是不占用额外的内存空间了吧
3 插入排序 ( Insertion Sort )
过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入
3.1 算法描述
- 从第一个元素开始,该元素可以被认为已经被排好序