算法笔记-2月8号

 

记录今天的“算法第四版”进度

今天学习的内容有:插入排序(insertion sort)和希尔排序(shell sort)讲解了排序的一个应用,洗牌(shuffling),那么下面我将简单的总结下今天的学习内容,当作一种记录和复习。

选择排序(selection sort)

我们将索引先放在i=0上,设其为最小值,然后在子循环中遍历与其他元素进行大小比较,若小于该元素则进行位置交换。此时不难想到我们就找到了数组中的最小值,因为该元素比其他任意元素都要小,因此我们把该元素放在第一位,然后把索引i加一,找到剩余元素中的最小值,交换位置,以此类推,直到i的数值为N-1,此时的数组已经有序。

对于N长度的数组来说,选择排序需要做{~}\frac{​{n}^2}{2}次比较(N-1+N-1+...+1)以及N次交换(这一点不是很懂,感觉找到小的就交换的话第一轮就不止1次了,那么怎么样都会超出N次)也存在位置正确的情况!因此只需要进行比较不需要进行交换!所以是最多N次!

public class Selection 
{ 
 public static void sort(Comparable[] a) 
 { // 将a[]按升序排列
 int N = a.length; // 数组长度
 for (int i = 0; i < N; i++) 
 { // 将a[i]和a[i+1..N]中最小的元素交换
 int min = i; // 最小元素的索引
 for (int j = i+1; j < N; j++) 
 if (less(a[j], a[min])) min = j; 
 exch(a, i, min); 
 } 
 } 
 // less()、exch()、isSorted()和main()方法见“排序算法类模板”
}

插入排序(Insertion sort)

与选择排序不一样,插入排序不需要做非常多次比较操作,而是需要做更多次换位操作,选择排序对于已经排列好的一组数据进行排序和完全打乱的数据进行排序,其花费的时间是没有差别的,但是插入排序考虑到了数组本身并不完全是无序的,其中有原本就是顺序的数据,也有逆序的数据,其中逆序的数据越多,插入排序所需要花费的时间越久。

因此,在插入排序中,我们需要做的事情有:

  1. 将索引定在数组的n=1的位置上,遍历整个数组
  2. 在第一个循环内,将第n个索引所对应的数据与前一个进行比较,如果逆序就进行交换,直到第一个数据,此时n之前的数据已经是有序的。

其最差情况为{~}\frac{​{n}^2}{2}次比较以及{~}\frac{​{n}^2}{2}次交换,最好情况为N-1次比较,0次交换。

public class Insertion 
{ 
 public static void sort(Comparable[] a) 
 { // 将a[]按升序排列
 int N = a.length; 
 for (int i = 1; i < N; i++) 
 { // 将 a[i] 插入到 a[i-1]、a[i-2]、a[i-3]...之中
 for (int j = i; j > 0 && less(a[j], a[j-1]); j--)
 exch(a, j, j-1); 
 } 
 } 

}

可视化如下:

希尔排序(Shell sort) 

那么还有什么方法可以缩减运算量呢?我们注意到插入排序其实做了很多没有必要或者说是多余的换位操作,有些元素的位置本来就是正确的。

希尔排序的思想是使数组中任意间隔为 h 的元素都是有序的。这样的数组被称为 h 有序数组 。换句话说,一个 h 有序数组就是 h 个互相独立的有序数组编织在一起组成的一个数组。在进行排序时,如果 h 很大,我们就能将元素移动到很远的地方,为实现更小的 h 有序 创造方便。
h有序数组
h有序数组

 

我们注意到一个非常有意思的性质,比如说我们先对一组数据进行h=7的有序排列 ,再进行h=3的有序排列,那么此时的排列对于h=7的情况来说依旧是有效的。按照h=3x+1的办法来进行h有序数组排序,就可以节省很大一部分的交换操作,减少实际的操作时间。

其比较次数为N^(3/2)

代码如下(摘自算法第四版)

public class Shell 
{ 
 public static void sort(Comparable[] a) 
 { // 将a[]按升序排列
 int N = a.length; 
 int h = 1; 
 while (h < N/3) h = 3*h + 1; // 1, 4, 13, 40, 121, 364, 1093, ... 
 while (h >= 1) 
 { // 将数组变为h有序
 for (int i = h; i < N; i++) 
 { // 将a[i]插入到a[i-h], a[i-2*h], a[i-3*h]... 之中
 for (int j = i; j >= h && less(a[j], a[j-h]); j -= h) 
 exch(a, j, j-h); 
 } 
 h = h/3; 
 } 
 }
 // less()、exch()、isSorted()和main()方法见“排序算法类模板”
}

希尔排序的可视化

 洗牌今天懒得写了。

课后习题:

1. Show in the style of the example trace with selection sort, how selection sort sorts the array

solution:

2. What is the maximum number of exchanges involving any particular item during selection sort? What is the average number of exchanges involving an item?

Solution. The average number of exchanges is exactly 1 because there are exactly N exchanges and N items. The maximum number of exchanges is N, as in the following example.

3. Which method runs fastest for an array with all keys identical, selection sort or insertion sort?

Solution. Insertion sort runs in linear time when all keys are equal(注:为什么相等时是linear time呢?)因为相等的时候,由于判断条件是索引的元素和索引-1对应的元素比较,因此如果不符合条件就直接跳出了,不需要进行多次比较,此处不需要多次比较的原因在于前面已经有序,若是索引 j 对应的元素更大或者相等,那么就不需要多做比较。

 

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值