经典排序算法分析及其Java实现

排序可分为两种:内排序和外排序。在排序过程中,全部记录存放在内存,称为内排序;如果排序过程中需要使用外存,则成为外排序。
内排序有以下几类:

各种内部排序算法的比较

直接插入排序、气泡排序和简单选择排序是基本的排序方法。它们平均情况下的时间复杂度都是 O(n2) ,它们的实现也都非常简单。
直接插入排序对于规模很小的元素序列 (n25) ,可以说是非常有效的。它的时间复杂度与待排序元素序列的初始排列有关。在最好情况下,直接插入排序只需要n-1次比较就可以完成,而且不需要交换。在平均情况下和最差情况下,直接插入排序的比较和交换都是 O(n2)
改进的冒泡排序在最好情况下只需要一趟冒泡过程就可以完成,此时也只需要 n1 次比较就可以了。
简单选择排序的排序码比较次数与待排序元素序列的初始排列无关,其比较次数总是 O(n2) ,但元素移动次数则与待排序元素序列的初始排列有关,最好情况下一次也不移动,最差情况下元素移动次数不超过 3(n1) 次。
从内存复杂度来看,这三种基本的排序方法除了一个辅助元素外,都不需要其他额外的内存空间。从稳定性来看,直接插入排序和冒泡排序都是稳定的,但简单选择排序不是。它们主要用于元素个数n不是很大 (<10K) 的情形。
快速排序是最通用的高效的内部排序算法,平均情况下的时间复杂度为 O(nlog2n) ,一般情况下所需要的额外内存也是 O(log2n) 。但是快速排序是个不稳定的算法。并且在有些情况下可能会退化(例如元素序列已经有序时),时间复杂度会增加到 O(n2) ,空间复杂度也会增加到 O(n) 。改进的快速排序算法,即三路划分的快速排序算法,能够有效地避免最坏情况的发生。
堆排序也是一种高效的内部排序算法,它的时间复杂度是 O(nlog2n) ,而且没有什么最坏情况会导致堆排序的运行明显变慢,并且堆排序基本不需要额外的内存空间。但堆排序不太可能提供比快速排序更好的平均性能。堆排序是一种不稳定的排序算法。
归并排序也只一个重要的高效排序算法它的性能与输入元素序列无关,时间复杂度总是 O(nlog2n) 。但它的主要缺点是直接执行时需要 O(n) 的附加内存空间,虽然有方法可以克服这个缺点,但是其代价是算法会很复杂且时间复杂度会增加,因此在实际应用中一般不值得这样做。归并排序算法是一种稳定的高效排序算法。
快速排序、堆排序和归并排序适合于元素个数n很大的情况。
希尔排序的时间复杂度介于基本排序算法和高效排序算法之间,虽然迄今为止对其性能的分析还是不精确的,但是希尔排序代码简单,基本不需要什么额外内存,空间复杂度低。希尔排序是一种不稳定的排序算法。对于中等规模的元素序列 (n1000) ,希尔排序是一种很好的选择。
基数排序是一种相对特殊的排序算法,这类算法不仅是对元素序列的排序码进行比较,更重要的是它们对排序码的不同部分进行处理和比较。虽然基数排序具有线性增长的时间复杂度,但是由于在常规编程环境中,关键字索引统计程序内部循环中包含大量操作,其数目比快速排序或者归并排序算法的内部循环多得多。所以基数排序的线性时间开销实际上不比快速排序的时间开销小很多。并且由于基数排序基于的排序码抽取算法受到操作系统和排序元素的影响,其适应性远不如普通的比较和交换操作。因此在实际工作中,常规的高效排序算法如快速排序的应用要比基数排序广泛得多。

排序方法时间复杂度空间复杂度稳定性
直接插入排序O(n2)O(1)
二分法插入排序O(nlog2n)O(1)
希尔排序-O(1)
简单选择排序O(n2)O(1)
堆排序O(nlog2n)O(1)
冒泡排序O(n2)O(1)
快速排序O(nlog2n)O(log2n)
归并排序O(nlog2n)O(n)
基数排序O(d(n+rd))O(rd)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值