数据结构之常用的内部排序

写在前面

对于一个排序算法来说,一般从如下三个方面来衡量算法的优劣:

》时间复杂度:主要是分析关键字的比较次数和记录的移动次数

》空间复杂度:分析排序算法需要多少辅助内存

》稳定性:若两个记录A和B的关键字相等,但排序后A,B的先后次序保持不变,则称这种排序算法是稳定的;反之就是不稳定的。


排序分为内部和外部排序的依据是:

如果整个排序过程不需要借助于外部存储器,所有排序操作都放在内存中完成,则为内部排序

常用的内部排序的分类

》选择排序:直接选择排序,堆排序

》交换排序:冒泡排序,快速排序

》插入排序:直接插入排序,折半插入排序,shell排序

》归并排序

》同时排序

》桶式排序

》基数排序


选择排序

只要找到本趟比较中最小的数据,然后拿他和本趟比较中第一位的数据交换。

对于直接选择排序来说,假设有n个数据,数据交换的次数最多有n-1次,但程序的比较次数较多(交换的次数有一些没有必要)。

总体来说,其时间效率为O(n^2)

根据代码结果:直接选择排序是不稳定

 

堆排序

最小堆(树中所有节点都小于其左右子节点的值)和最大堆(树中所有节点都大于其左右子节点的值),分别对应着一棵完全二叉树

对于n个数据元素的数据组而言,堆排序需要经过n-1次建堆,每次建堆的作用就是选出该堆的最大值或最小值。堆排序的本质是一种选择排序

 

堆排序的关键在于建堆

1.从最后一个非叶节点开始,比较该节点和它两个子节点的值;如果某个子结点大于父节点的值,就把父节点和较大的子节点进行交换

2.向前逐步调整直到根节点,即保证每个父节点的值都大于等于其左右子节点的值,建堆完成。

 

对于堆排序来说,假设有n个数据,需要进行n-1次建堆,每次建堆本身耗时log2,n;则其时间效率是O(n*log2,n

堆排序的空间效率很高,它只需要一个附加程序单元用于交换,其空间效率为O(1)

从堆排序的结果来看,它是不稳定的

 

冒泡排序

冒泡排序是最广为人知的交换排序之一,,它具有算法思路简单,容易实现的特点

冒泡排序的每趟交换结束后,不仅能将当前最大值挤出最后面的位置,还能部分理顺前面的其他元素;一旦某一趟没有交换发生,即可提前结束排序。

 

冒泡排序算法的时间效率是不确定的,在最好的情况下,初始序列已经在有序状态,则执行一次冒泡即可,即做n-1次比较,无需交换。

但在最坏的情况下,初始数据序列处于完全逆序状态,算法要执行n-1趟冒泡,第i趟做了n-i个比较,

冒泡排序的空间效率很高,它只需要一个附加程序单元用于交换,O(1)

冒泡排序是稳定的

 

快速排序

是一个速度非常快的交换排序算法

基本思路比较简单:

从待排序的数据序列中人去一个数据(如第一个数据)作为分界值,所有比它小的数据元素一律放在左边,所有比它大的数据元素一律放在右边,经过这样一趟下来,该序列形成两个子序列,接下来对左右两个子序列进行递归,对两个子序列重新选择中心元素并依此调整,直到每一个子序列中的元素只剩一个,排序完成。

快速排序只进过两次交换即可让分界值左边的数据小于分界值,分界值右边的数据大于分界值,因此速度很快。


快速排序的时间效率很好,因为它每趟能确定的元素成指数级增长

快速排序需要使用递归,而递归使用栈,因此它的空间效率为O(log2.n)

另一方面,快速排序这种包含跳跃交换,因此是不稳定的排序算法


插入排序

》直接插入排序

》shell排序

》折半插入排序


直接插入排序

思路很简单:将待排序的数据元素按其关键字的值的大小插入前面的有序序列

直接插入排序的时间效率并不高,在最坏的情况下,所有 元素的比较次数总和为(0+1+2。。。+n-1)=O(n^2)

在其他情况下,也要考虑移动元素的个数,故时间复杂度为O(n^2)

直接插入排序的空间效率很好,他只需要一个缓存数据单元,空间效率为O(1)

稳定的


折半插入排序

折半插入排序是对直接插入排序的简单改进

对于折半插入排序而言,当第i-1趟需要将第i个元素插入前面的0~i-1个元素序列中,他不会直接从第i-1个元素开始比较:

1.计算0~i-1索引的中间点,也就是用i索引处的元素和(0+i-1)/2索引处的元素来进行比较,如果i索引处的元素大,就在另一半的范围内搜索,这就是所谓的折半。

2.不断的折半,将搜索范围缩小到1/2,1/4,1/8.从而快速确定第i个元素的插入位置。

3.确定插入位置后,程序将位置以后的元素整体后移一位,然后将第i个元素放入该位置。

稳定的


shell排序

希尔排序对直接插入排序进行了改进:它通过加大插入排序中元素的间隔,并在这些有间隔的元素中进行插入排序,从而使数据项大跨度的移动。

通过创建这些交错的内部有序的数据项集合,就可以减少直接插入排序中数据项”整体搬家“的工作量


希尔排序比插入排序快很多,当间隔即增量h大的时候可以减少很大的移动量,因此效率很高。

shell排序是直接插入排序的改进版,因此也是稳定的,它的空间开销也是O(1)

时间开销大致是O(n的3/2次方)到n的7/6次方)之间


归并排序

”合并排序“:将两个有序的数组进行合并,成为一个新的有序大数组。

归并算法需要递归地进行分解,合并,每进行一趟归并排序需要调用merge(、)方法一次,每次执行merge()算法都要比较n次,因此归并排序算法的时间复杂度是O(n*log2.n)

归并算法的的空间效率比较差,它需要一个与原始序列同样大小的辅助序列

归并排序算法是稳定的


桶式排序

不是一个基于比较的排序方法这种排序方式必须满足两个特征:

》待排序的所有值在一个可枚举范围内

》待排序的可枚举范围不应太大,否则排序开销太大


桶式排序算法是一种极其优秀的算法,时间效率极高,它只需要两轮遍历即可:

第一轮遍历待排数据,统计每个待排数据落入各个桶中的个数;

第二轮遍历用于重新计算每一个桶里的数组元素的值

两轮遍历后就可得到每个待排数据的在有序序列中的位置,然后将每一个数据依次放入指定位置即可

桶式排序的空间开销较大,他需要两个数组

桶式排序数稳定的


猜你喜欢

转载自blog.csdn.net/Hyo555/article/details/79947827