各类排序方法小结

来源:互联网 发布:c指针的编程题 编辑:程序博客网 时间:2024/05/26 05:50

1. 插入排序

a) 直接插入排序

0开始构建一个有序序列,把无序序列中的数字一一插入有序数列中(可以共用一个数组)。插入的时候,就是从头比较。

平均:O(n²)

最坏:O(n²)

空间:O(1)

 

b) 折半插入排序

就是在直接插入排序基础上,插入有序序列的时候采用了折半查找。

时间复杂度上,仅仅减少了比较(查找)的次数,但记录移动次数不变,时间复杂度和空间复杂度均同a)

 

c) 2-路插入排序

2的一种排序,本质上还是和折半插入排序一样;只不过选取无序数列的第一个数,以此为标准分为两个有序数列,然后插入的时候就可以减少一半的移动次数(查询仍然可以按照折半插入排序来,实现起来,应该就是分成两个序列后,对每一个插入的数字,选择一个有序序列调用b)

这个排序多了一个序列的空间;时间减少一半;记录移动次数约为n²/8. 但是复杂度仍然是O(n²)


d) 表插入排序

表插入排序适合静态链表的存储结构适合的排序(静态链表:数组+链表)。基本的思想也是插入,插入的方式其实就是修改指针,不需要记录移动。但是排序完成后,由于是链表结构,没办法随机查询,如果要随机查询,需要再把这些链表重新按照其数组下标大小进行排序。用到了时候再详细使用吧。

时间复杂度还是O(n²)


e) 希尔排序

又称为缩小增量排序。按照一定的增量k,把原序列划分为k个子序列,对这k个子序列分别进行插入排序,称为一趟排序。然后k减小一些,再进行一趟排序,直到k=1这一趟排序完成后,排序完成。

时间复杂度大概是O(n**1.3~n**1.5)这样。取决于增量k的序列。


2. 交换排序

a) 冒泡排序

冒泡法就不说了,很简单。没什么注意的,除了和简单选择排序区分一下。时间复杂度O(n**2)

b) 快速排序

基本思想:选择数列中的一个pivotKey,将数列分为两个子数列,大于pivotKey和小于pivotKey。然后对每个子序列分别进行快速排序。

分成两个子序列的方法很有意思:从序列两端的指针向中间移动:下标low增加,high减少;如果low指向的key大于pivotKey,将该值换到high上面,high开始减少。反正亦然;直到low == high,这时候lowhigh所指位置即为pivotKey位置。

平均时间复杂度:O(k n ln(n))k是一个常数;是目前所有内部排序中最快的方法。

最坏时间复杂度:O(n²同冒泡排序,可以按照“三者取中”法则来选取pivotKey,从而改善最坏情况的性能。


3. 选择排序

a) 简单选择排序

打擂台排序,我不动脑子就写出来的那个排序。

b) 树形选择排序

仍然是打擂台排序,但是这次不仅要第一名,而且要第二名第三名的打擂台了,所以用一种二叉树结构来进行比较。每一次比较都可以选出一个最小的,然后把选出的位置换成无穷大,再次比赛,出来次小的,以此类推,最后排序。时间复杂度O(n log n),但是缺点是所需要的空间很多。

c) 堆排序

一个时间复杂度为O(n log n),空间复杂度为O(1)的排序,本质上是树形排序的改进,按照堆的定义构成一个完全二叉树,然后从堆顶端输出最小值/最大值,再把堆的最后一个替换到堆的第一个后进行调整。整个排序算法主要完成两个步骤:1. 建一个堆;2. 调整堆顶元素重新构成一个堆。具体方法在此不相信叙述。


4. 归并排序

递归的把两个有序序列合并到一个序列。时间复杂度O(n log n). 是一种稳定的排序。


5. 基数排序Radix Sorting

a) 多关键字排序

这个不是要探讨的问题,而是只当一个序列有多个关键字时候,排序的方式,包括MSDLSD。典型的例子是扑克牌排序,按照花色和面值两个关键字排序,可以有MSDLSD两种不同的方式。这里我们假设花色是主关键字的话,则MSD即先按照花色分成四堆牌,然后再在每一堆牌里面按照面值排序,最后四堆牌合起来;LSD则是先按照面值分成13堆牌,合起来,然后再按照花色进行稳定的排序(即想等的值,原来在前面的还是在前面),这样也可以排好。

b) 链式基数排序

链式基数排序借助多关键字排序的思想,首先把单个关键字分割成多个关键字(比如,关键字是0-999的数值,可以分成百位数,十位数,个位数三个关键字),然后按照LSD方式对这些关键字重新排序,这样只需要三趟排序就可以完成。用链表的方式来排序最省空间,所以称为链式基数排序。对于n个记录,记录含有d个关键字且关键字取值范围是rd个值(比如上面例子,d = 3 , rd = 10),则其时间复杂度为O(d(n + rd)),即每一趟分配时间为n, 收集时间为rd, 共需进行d趟。需要rd个表头和表尾来作为辅助存储空间。

 

 

6. 排序总结:

基于上述排序方法,可以分成以下几类排序:

a) 简单排序:包括直接插入(改进:折半插入,2-路插入),冒泡排序,简单选择

b) 快速排序(基于冒泡排序)

c) 归并排序(基于归并两个有序数组)

d) 堆排序(基于树形选择排序)

e) 基数排序(基于多关键字排序)

f) 希尔排序(基于插入排序)

其中简单排序时间复杂度均为O(n²), 三个高级排序,快速,归并,堆均为O(n log n),基数排序为O(d ( n + rd)),希尔排序是O(n**1.3~n**1.5). 空间复杂度各异。

 

还要注意的一个问题是,如果待排序的每一个记录很大,交换移动需要花费大量时间,则可以考虑使用表排序方式来减少移动次数。大致的思路是,建立一个静态链表,先用选择的排序方法在将指针排好序(链表排序),再用一个方法,通过有序的指针来对记录排序,从而达到记录有序。

 

0 0
原创粉丝点击