第二章 2.1初级排序算法

在本章中,我们将学习几种经典的排序算法,并高效地实现了“优先队列”这种基础数据类型。我们将讨论比较排序算法的理论基础并在本章结束总结若干排序算法和优先队列的应用。

2.1.1 游戏规则
 
      我们关注的主要对象是重新排列数组元素的算法,其中每个元素都有一个主键。排序算法的目标是将所有元素的主键按照某种方式排列。 元素和主键的具体性质在不同的应用中千差万别。在java中,元素通常都是对象,对主键的抽象描述则是通过一种内置的机制来完成的。
      “排序算法类模板”中的example 类展示了我们的习惯约定:我们会就爱个排序代码放在类的sort()方法中,该类还将包含辅助函数less(对元素进行比较)和exch(将元素交换位置)以及一个示例用例main()。



运行时间

我们要评估算法的性能
  • 计算各个排序算法在不同的随机输入下的基本操作的次数。
  • 我们用这些数据估计算法的相对性能并介绍在实验中验证这些猜想所使用的工具。
排序成本模型:在研究排序算法时,我们需要 计算比较和交换的数量。对于不交换元素的算法,我们会计算 访问数组的次数

排序算法分类:(1)除了函数调用所需的栈和固定数目的实例变量之外无需额外内存的原地排序算法。(2)以及需要额外内存空间来存储另一份数组副本的其他排序算法。

数据类型

我们的排序算法模板适用于任何实现了comparable接口的数据类型。在创建自己的数据类型时,我们只o要实现了Comparable接口就能够保证用例代码可以将其排序。当然,还需要实现compareTo方法来定义目标类型对象的自然次序。(通过此,我们可以看出如果一个自定义的数据类型实现了comparable 接口的话,那么他们就可以通过排序算法进行排序)





选择排序

 选择排序的内循环是在比较当前元素和目前已知的最小元素,交换元素的代码写在内循环之外,每次交换就能排定一个元素。因此交换的总次数为N,所以选择算法的时间效率取决于比较的次数。选择排序需要大约N^2/2次比较和N次交换。
  • 命题A:对于长度为N的数组,选择排序需要大约N^2/2次比较和N次交换。
  • 证明:可以通过算法的排序轨迹来证明这一点。对角线上和其上的元素都需要比较一次,对角线上的每个元素都对应着一交换。

选择算法的特点:
  • 运行时间与输入无关。选择算法为了找最小的元素会扫描一遍数组,也就是说无论数组是有序的还是乱序的,使用选择算法排序的时间是一样的。其他算法会更善于利用输入的初始状态。
  • 数据移动最少,每次交换都会改变两个数组元素的值,因此选择排序用了N次交换---交换的次数和数组的大小是线性关系。



插入排序

插入排序是将每一张牌插入到其他已经有序的牌中的适当位置,其他无序的则需要向右移动一位,这种算法叫做插入算法。对于使用插入排序我们考虑的数组的一般情况是部分有序的数组。倒置指的是数组中的两个顺序颠倒的元素。如果数组中倒置的数量小于数组大小的某个倍数,那么我们说这个数组是部分有序的。
与选择排序相比:插入排序所需的时间取决于输入中元素的初始顺序。

插入排序对于那种部分有序的数组很有效,而选择排序则不然事实上,当倒置的数量很少时,插入排序很可能比本章中的其他任何算法都快。部分有序数组包括:
  1. 数组中每个元素距离它的最终位置都不远。
  2. 一个有序的大数组接一个小数组;
  3. 数组中只有几个元素的位置不正确。


  • 命题B:对于随机排列的长度为N 且主键不重复的数组,平均情况下插入排序需要~N^2/4次比较以及~N^2/4次交换。最坏情况下需要~N^2/2次比较和~N^2/2交换。最好情况下需要N-1次比较和0次交换
  • 证明:通过一张N*N轨迹表,我们可以得到,最坏情况下对角线之下的所有元素都需要移动位置,最好情况下都不需要。对于随机排列的数组,在平均情况下每个元素都可能向后移动半个数组的长度,因此交换总数是对角线之下的元素总数的二分之一。比较的总次数是交换的次数加上一个额外的项,该项为N减去被插入的元素正好是已知的最小元素的次数。在最坏情况下,这一项相对于总数可以忽略不计; 最好情况下,这一项等于N-1;

  •  命题C:插入排序需要的交换的操作和数组中倒置的数量相同,需要比较的次数大于等于倒置的数量,小于等于倒置的数量加上数组的大小再减一。
  • 证明:每次交换就改变了两个元素的位置,一次交换,相当于减少一次倒置,当倒置数量为0时,排序就完成了。每次交换都对应着一次比较,且1到N-1之间的每个i都可能需要一次额外的比较。    


比较两种排序算法

利用系统的时差和求出排序算法的效率。



希尔排序

       希尔排序是一种基于插入排序的快速的排序算法。对于大规模乱序数组插入排序很慢,因为它知乎交换相邻的元素,因此元素智能一点一点地从数组的一端移动到另一端。希尔排序为了加快速度简单地改进了插入排序。交换不相邻的元素以对数组的局部进行排序,并最终用插入排序将局部有序的数组排序。
        缺点:希尔排序是我们唯一无法准确描述其对于乱序的数组的性能特征的排序方法

      希尔排序高效的原因是:它会权衡子数组的规模和有序性。对于实验而言,希尔排序比插入排序和选择排序要快的多,并且数组越大,优势越大。
     此次希尔排序解决了一些初级排序算法无能为力的问题,而这说明一个贯穿本书的重要概念:通过提升速度来解决其他方式无法解决的问题是研究算法的设计和性能的主要原因之一。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值