Week 2.2 | Elementary sort | Princeton Algorithms

一、Comparable接口和Comparator

这个也是61B讲的更详细,略

1. Comparable接口

简单来说,就是implements Comparable接口的类,都需要具有CompareTo方法,这样就可以进行比较了。
此外,实现了CompareTo方法后,可以使用库函数的sort方法对该对象进行排序。

CompareTo方法定义的顺序是sort所采用的顺序,成为自然顺序。

2. Comparator

可以使用不同的比较方法对两个对象进行比较。例如CompareTo方法对一个人的名字进行排序,而在不同的comparator中,可以对其身高、年龄、成绩等进行排序。

库函数:
在这里插入图片描述
比较器的实现:

  1. 在当前类中实现一个嵌套类private static class ByName implements Comparator<Student>,其中实现compare方法。在当前类中添加public static变量public static final Comparator<Student> BY_NAME = new ByName();,让其他类可以直接调用该变量。
  2. 或者不适用变量,而是添加一个静态方法public static Comparator<Student> getNameComparator()return new NameComparator();

二、基础排序方法

1. 选择排序

  • idea:
    使用一个指针,从左到右移动。指针每移动一个元素,就在指针所指元素的右边遍历寻找到一个最小值,将其与指针所指的元素交换。
  • 该算法的不变性:
    • 指针的左边的元素是固定且升序的
    • 指针右边的元素都大于指针左边的元素
  • 实现:
    在这里插入图片描述
    在这里插入图片描述
  • 复杂度分析:N2

2. 插入排序

  • idea:
    一个指针从左到右移动,指针每移动一个元素,就将指针所指向的元素插入到指针左侧的升序数组中合适的位置,具体方法是,将指针所指向的元素与其左侧的元素交换再交换,直到交换至其左侧元素比它小为止。
  • 不变性:
    • 指针左侧的元素是升序的
    • 指针右侧的元素从未访问过
  • 实现:
    在这里插入图片描述
  • 复杂度分析:插入排序的独特之处就在于,它的复杂度很依赖数组的初始顺序
    • 随机排序的数组,复杂度1/4*n2
      在这里插入图片描述
    • 按升序排好的数组,复杂度为线性,因为只需要比较n次,不需要交换。(而选择排序仍然是n2,因为仍然要遍历)
    • 按降序排列的数组(即完全反向顺序),复杂度为1/2*n2
    • 部分有序的数组,复杂度介于线性和n2之间。比如,由一对对反向数对组成的数组(即,2,1,4,3,6,5,8,7),选择排序复杂度为线性,因为只需要比较n次并交换n/2次。

3. 希尔排序Shellsort

依据选择排序的特性,设计了希尔排序。

  • idea:
    以h为步长,将指针p指向的元素与p-h个元素进行比较,如果p元素比p-h元素小,则交换p元素和p-h元素。再将h变小,重复上述过程。直到h=1,再进行选择排序,完成排序过程。
    和选择排序原理相同,只不过选择排序的步长一直为1,只与前一个元素比较和交换,而希尔排序的步长从大到小变化。这样做的目的是让数组成为部分有序的,从而降低选择排序的时间。
    在这里插入图片描述
  • 实现:常用的h序列是3x + 1. 即 1, 4, 13, 40, 121, 364, …
    在这里插入图片描述
  • 复杂度分析:还没有具体的数学模型,只能利用比较次数估计
    在这里插入图片描述

三、应用

1. 洗牌

  • 方法1:使用排序将牌按随机顺序排好,所以要写一个产生随机顺序的CompareTo方法,再使用排序方法即可:
 public int compareTo(Browser that) {
     double r = Math.random(); 
     if (r < 0.5) return -1; {
        if (r > 0.5) return +1; 
           return 0; 
        }
 }
  • 方法2:任意交换两张牌
    在这里插入图片描述

但这样都有bug,因为random()方法貌似无法让洗牌的概率做到绝对均匀,还有一些其他bug。PPT中说,可以通过改进硬件和算法改进这些问题。比较复杂,略。

2. Convex hull凸包

  • 问题描述:
    在这里插入图片描述
    逆时针输出凸包顶点。所谓的凸包就是一堆点中的一个点集,该点集能够包围住所有的点,并使周长最小。
  • 等价定义:
    ・Smallest convex set containing all the points.包含所有点的最小凸集。
    ・Smallest area convex polygon enclosing the points. 包围所有点的最小面积的凸多边形。
    ・Convex polygon enclosing the points, whose vertices are points in set.包围点的凸多边形,其顶点是集合中的点。
  • 凸包的应用:
    • 机器人移动轨迹
      在这里插入图片描述
    • 寻找距离最远的两点
      在这里插入图片描述
  • 凸包的几何性质:
    • 只能通过逆时针旋转来穿过凸包。
    • 凸壳的顶点相对于点p的极角呈递增的顺序,其中点p的纵坐标最低。
  • 凸包的实现idea(依据几何性质):
    ・Choose point p with smallest y-coordinate.
    ・Sort points by polar angle with p.
    ・Consider points in order; discard unless it create a ccw turn.
    比如:
    从1到2,是逆时针的,可以;从2到3,是逆时针的,也可以;但是从3到4,不是逆时针的,所以不行,丢弃掉4.
    再看3到5,不是逆时针的,不行,丢弃掉3.
    再看2到5,不是逆时针的,不行,丢弃掉2.
    再看1到5,是逆时针的,可以
    以此类推
    在这里插入图片描述
  • 凸包的实现细节
    在这里插入图片描述
  • 实现判断逆时针:
    在这里插入图片描述
    在这里插入图片描述
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值