【Java排序算法】排序算法

排序算法

所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作。排序算法,就是如何使得记录按照要求排列的方法。排序算法在很多领域得到相当地重视,尤其是在大量数据的处理方面。一个优秀的算法可以节省大量的资源。在各个领域中考虑到数据的各种限制和规范,要得到一个符合实际的优秀算法,得经过大量的推理和分析。

所谓排序算法,即通过特定的算法因式将一组或多组数据按照既定模式进行重新排序。这种新序列遵循着一定的规则,体现出一定的规律,因此,经处理后的数据便于筛选和计算,大大提高了计算效率。对于排序,我们首先要求其具有一定的稳定性,即当两个相同的元素同时出现于某个序列之中,则经过一定的排序算法之后,两者在排序前后的相对位置不发生变化。换言之,即便是两个完全相同的元素,它们在排序过程中也是各有区别的,不允许混淆不清。

评价标准

稳定性是一个特别重要的评估标准。稳定的算法在排序的过程中不会改变元素彼此的位置的相对次序,反之不稳定的排序算法经常会改变这个次序,这是我们不愿意看到的。我们在使用排序算法或者选择排序算法时,更希望这个次序不会改变,更加稳定,所以排序算法的稳定性,是一个特别重要的参数衡量指标依据。就如同空间复杂度和时间复杂度一样,有时候甚至比时间复杂度、空间复杂度更重要一些。所以往往评价一个排序算法的好坏往往可以从下边几个方面入手:

  • 时间复杂度:即从序列的初始状态到经过排序算法的变换移位等操作变到最终排序好的结果状态的过程所花费的时间度量。
  • 空间复杂度:就是从序列的初始状态经过排序移位变换的过程一直到最终的状态所花费的空间开销。
  • 使用场景:排序算法有很多,不同种类的排序算法适合不同种类的情景,可能有时候需要节省空间对时间要求没那么多,反之,有时候则是希望多考虑一些时间,对空间要求没那么高,总之一般都会必须从某一方面做出抉择。
  • 稳定性:稳定性是不管考虑时间和空间必须要考虑的问题,往往也是非常重要的影响选择的因素。

插入类排序

插入类排序的基本思想:在一个已排好序的记录子集的基础上,每一步将下一个待排序的记录有序插入到已排好序的记录子集中,直到将所有待排记录全部插入为止。例如,打扑克牌时抓牌就是插入排序的一个很好的例子,每抓一张牌,插入到合适的位置,直到抓完牌为止,即可得到一个有序序列。

常见的插入类排序有:

插入排序

希尔排序

交换类排序

交换类的排序思想是通过一系列交换逆序元素进行排序的方法。

常见的交换类排序有:

冒泡排序

快速排序

选择类排序

选择类排序的基本思想是每一趟在n-i+1 (i=1,2,…,n-1)个记录中选取关键字最小的记录作为有序序列中第 i 个记录。

常见的选择类排序有:

选择排序

堆排序

归并排序

前面介绍的三类排序方法:插入排序、交换排序和选择排序,都是将一组记录按照关键字大小排成一个有序的序列。

归并排序基本思想是基于合并,将两个或者两个以上有序表合并成一个新的有序表。

下面进行详细介绍:

归并排序

各种排序方法的综合比较

我们从算法的平均复杂度、最坏时间复杂度以及算法所需要的辅助存储空间三个方面,对各种排序方法加以比较,如下表所示,其中简单排序法包括直接插入排序、冒泡排序和简单选择排序等。

排序方法 平均时间复杂度 最坏时间复杂度 辅助存储空间
简单排序法 O(n^2) O(n^2) O(1)
快速排序 O(nlog2n) O(n^2) O(log2n)
堆排序 O(nlog2n) O(nlog2n) O(1)
归并排序 O(nlog2n) O(nlog2n) O(n)
基数排序 O(d(n+rd)) O(d(n+rd)) O(rd)

下面再从排序方法的稳定性角度,对各种排序方法加以比较。

排序方法的稳定性:假设Ki = Kj (1<=i<=n,1<=j<=n,i!=j),若在排序前的序列中Ri领先于Rj(即i

证明一种排序方法是稳定的,要从算法本身的步骤中加以证明。证明排序方法是不稳定的,只需给出一个反例说明。

在多数情况下,排序是按记录的主关键字进行的,此时不必考虑排序方法的稳定性。如果排序是按记录的次关键字进行的,则应充分考虑排序方法的稳定性。

例如,一组学生记录已按学号排好序,现在需要根据学生的入学总分进行排序,当总分相同时,要求学号小的在前面。显然,在按入学总分进行排序时,必须选用稳定的排序方法。

各种排序方法的稳定性如表所示:

排序方法 稳定性 反例
直接插入排序
冒泡排序
简单选择排序 (3,3,2)
希尔排序 (2,4,1,2) d1=2,d2=1
快速排序 (3,2,2
堆排序 (5,5,3)
归并排序
基数排序

综合分析和比较各种排序方法,可以得出以下结论:

  • 1、简单排序法一般只适用于n较小的情况(例如n<30)。当序列中的记录“基本有序”时,直接插入排序是最佳的排序方法。如果记录中的数据较多,则应采用移动次数较少的简单选择排序法。
  • 2、快速排序、堆排序和归并排序的平均时间复杂度均为O(nlog2n),但实验结果表明,就平均时间性能而言,快速排序是所有排序方法中最好的。遗憾的是,快速排序在最坏情况下的时间性能为O(n^2)。堆排序和归并排序的最坏时间复杂度仍为O(nlog2n),当n较大时,归并排序的时间性能优于堆排序,但它所需的辅助空间最多。
  • 3、可以将简单排序法与性能较好的排序方法结合使用。例如,在快速排序中,当划分子区间的长度小于某值时,可以转而直接调用直接插入排序法;或者先将待排序列划分成若干子序列,分别进行直接插入排序,然后再利用归并排序法,将有序子序列合并成一个完整的有序序列。
  • 4、基数排序的时间复杂度可以写成O(dn)。因此,它最适用于n值很大而关键字的位数d较小的序列。当d远小于n时,其时间复杂度接近于O(n)。
  • 5、从排序的稳定性上来看,在所有简单排序法中,简单选择排序是不稳定的,其他各种简单排序法都是稳定的。然而,在那些时间性能较好的排序方法中,希尔排序、快速排序、堆排序都是不稳定的,只有归并排序、基数排序是稳定的。

综上所述,每一种排序方法各有特点,没有哪一种方法是绝对最优的。应根据具体情况选择合适的排序方法,也可以将多种方法结合起来使用。

你可能感兴趣的:(排序算法)