Callback = reference to executable code.
・Client passes array of objects to sort() function.
・The sort() function calls back object’s compareTo() method as needed.
Implementing callbacks.
・Java: interfaces.
・C: function pointers.
・C++: class-type functors.
・C#: delegates.
・Python, Perl, ML, Javascript: first-class functions.
接口(英语:Interface),在JAVA编程语言中是一个抽象类型(Abstract Type),它被用来要求类(Class)必须实现指定的方法,使不同类的对象可以利用相同的界面进行沟通。接口通常以interface来宣告,它仅能包含方法签名(Method Signature)以及常数宣告(变量宣告包含了 static 及 final),一个接口不会包含方法的实现(仅有定义)。
Comparable接口的定义(Java内置):
public interface Comparable-
{
public int compareTo(Item that);
}
Comparable接口使用示例:
Client端:
import java.io.File;
public class FileSorter
{
public static void main(String[] args)
{
File directory = new File(args[0]);
File[] files = directory.listFiles();
Insertion.sort(files);
for (int i = 0; i < files.length; i++)
StdOut.println(files[i].getName());
}
}
File类的实现:
public class File implements Comparable
{
...
public int compareTo(File b)
{
...
return -1;
...
return +1;
...
return 0;
}
}
sort方法的实现:
public static void sort(Comparable[] a)
{
int N = a.length;
for (int i = 0; i < N; i++)
for (int j = i; j > 0; j--)
if (a[j].compareTo(a[j-1]) < 0)
exch(a, j, j-1);
else break;
}
Total Order
A total order is a binary relation ≤ that satisfies:
・Antisymmetry: if v ≤ w and w ≤ v, then v = w.
・Transitivity: if v ≤ w and w ≤ x, then v ≤ x.
・Totality: either v ≤ w or w ≤ v or both.
在类中实现compareTo方法,使得v.compareTo(w)
・Is a total order.
・Returns a negative integer, zero, or positive integer
if v is less than, equal to, or greater than w, respectively.
・Throws an exception if incompatible types (or either is null).
排序算法的helper function:
// 判断v是否比w小。如果是则返回True
private static boolean less(Comparable v, Comparable w)
{ return v.compareTo(w) < 0; }
//交换数组中i和j两个元素的位置
private static void exch(Comparable[] a, int i, int j)
{
Comparable swap = a[i];
a[i] = a[j];
a[j] = swap;
}
private static boolean isSorted(Comparable[] a)
{
for (int i = 1; i < a.length; i++)
if (less(a[i], a[i-1])) return false;
return true;
}
步骤:
1. 从左到右扫描,In iteration i, find index min of smallest remaining entry.
2. Swap a[i] and a[min].
Invariants:
1. pointer左侧(包括pointer)的元素都是固定的,而且是从小到大的顺序
2. pointer右侧不存在比pointer左侧小的元素
public class Selection
{
public static void sort(Comparable[] a)
{
int N = a.length;
for (int i = 0; i < N; i++)
//从左到右移动pointer
{
//首先令最小的index为pointer的位置
int min = i;
//依次遍历pointer右侧的元素
for (int j = i+1; j < N; j++)
//如果小于当前的最小值
if (less(a[j], a[min]))
//min改为这个值的index
min = j;
exch(a, i, min);
}
}
private static boolean less(Comparable v, Comparable w)
{ /* as before */ }
private static void exch(Comparable[] a, int i, int j)
{ /* as before */ }
}
从左到右依次移动pointer,当pointer为index 0的时候,需要进行N-1次比较,之后N-2次,。。。,1,0,即 (N−1)N2 ~ N22 。exchange次数为N(包括自己和自己交换)。
特点:
1. 运行时间与输入无关,即便属于已经是排序好的还是要进行~ N22 次比较
2. 数据转移操作最小,只需N次交换
步骤:
从左到右移动pointer,在每一次循环i, 将a[i]和其左侧每一个更大的值进行交换
Invariants:
・Pointer左侧(包括pointer)的元素处于递增顺序
・Pointer右侧的元素还没见过
注意:
如果左边第一个元素已经比pointer位置的小了,就不会继续进行比较了,因为pointer左侧的元素已经处于递增的顺序。
public class Insertion
{
public static void sort(Comparable[] a)
{
int N = a.length;
//依次向右移动pointer
for (int i = 0; i < N; i++)
//依次将pointer与其左侧元素进行比较
//如果pointer位置比左侧的小,则与其交换,否则停止循环
for (int j = i; j > 0; j--)
if (less(a[j], a[j-1]))
exch(a, j, j-1);
else break;
}
private static boolean less(Comparable v, Comparable w)
{ /* as before */ }
private static void exch(Comparable[] a, int i, int j)
{ /* as before */ }
}
从左向右依次移动pointer,然后将pointer与左侧元素进行比较,如果比左侧元素小两者就交换,然后继续和新位置的左侧元素比较,因此复杂度取决于输入。
- 最好情况(输入已经是升序):
每次pointer只需比较一次,不需要交换位置,因此共N次比较,0次交换
- 最坏情况(输入是降序):
每次pointer都要与左侧所有元素比较一次,并且要与每个元素都要交换一次位置, 0+1+。。。+N−1=N(N−1)2 ,即~ N22 次比较,~ N22 次交换
想法:
因为insertion sort想要达到最终位置需要一次交换一个位置,通过h-sort来一次移动多个位置,并不断降低h。
如何h-sort?
以stride length h来进行insertion sort
A g-sorted array remains g-sorted after h-sorting it.
public class Shell
{
public static void sort(Comparable[] a)
{
int N = a.length;
int h = 1;
//首先确定h的最大值
while (h < N/3) h = 3*h + 1; // 1, 4, 13, 40, 121, 364, ...
while (h >= 1)
{ // h-sort the array.
for (int i = h; i < N; i++)
{
for (int j = i; j >= h && less(a[j], a[j-h]); j -= h)
exch(a, j, j-h);
}
h = h/3;
}
}
private static boolean less(Comparable v, Comparable w)
{ /* as before */ }
private static void exch(Comparable[] a, int i, int j)
{ /* as before */ }
}
The worst-case number of compares used by shellsort with
the 3x+1 increments is O(N3/2) .
Rearrange array so that result is a uniformly random permutation.
Shuffle sort 步骤:
・Generate a random real number for each array entry.
・Sort the array.
Knuth Shuffle:
・In iteration i, pick integer r between 0 and i uniformly at random.
・Swap a[i] and a[r].
public class StdRandom
{
...
public static void shuffle(Object[] a)
{
int N = a.length;
for (int i = 0; i < N; i++)
{
int r = StdRandom.uniform(i + 1);
exch(a, i, r);
}
}
}
定义:
The convex hull of a set of N points is the smallest perimeter fence enclosing the points
Convex hull的性质:
1. 在convex hull上运动可以只进行逆时针转动
2. convex hull的角点相对于y坐标最小的点p的极角是依次变大的
・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.