文章目录
一、Comparable接口和Comparator
这个也是61B讲的更详细,略
1. Comparable接口
简单来说,就是implements Comparable接口的类,都需要具有CompareTo方法,这样就可以进行比较了。
此外,实现了CompareTo方法后,可以使用库函数的sort方法对该对象进行排序。
CompareTo方法定义的顺序是sort所采用的顺序,成为自然顺序。
2. Comparator
可以使用不同的比较方法对两个对象进行比较。例如CompareTo方法对一个人的名字进行排序,而在不同的comparator中,可以对其身高、年龄、成绩等进行排序。
库函数:
比较器的实现:
- 在当前类中实现一个嵌套类
private static class ByName implements Comparator<Student>
,其中实现compare方法。在当前类中添加public static变量public static final Comparator<Student> BY_NAME = new ByName();
,让其他类可以直接调用该变量。 - 或者不适用变量,而是添加一个静态方法
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次。
- 随机排序的数组,复杂度1/4*n2
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,是逆时针的,可以
以此类推
- 凸包的实现细节
- 实现判断逆时针: