普林斯顿算法课Part 1 Week 2 Elementary Sorts

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Cyril__Li/article/details/79830263

1. Rules of the game

1.1 Java的Comparable接口

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<Item>
{
    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<File>
{
    ...
    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;
}

2. Selection Sort

步骤:
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左侧小的元素

这里写图片描述

2.1 Selection Sort:Java实现

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 */ }
}

2.2 Selection Sort复杂度分析

从左到右依次移动pointer,当pointer为index 0的时候,需要进行N-1次比较,之后N-2次,。。。,1,0,即 (N1)N2 ~ N22 。exchange次数为N(包括自己和自己交换)。

特点
1. 运行时间与输入无关,即便属于已经是排序好的还是要进行~ N22 次比较
2. 数据转移操作最小,只需N次交换

3. Insertion Sort

步骤:
从左到右移动pointer,在每一次循环i, 将a[i]和其左侧每一个更大的值进行交换

Invariants:
・Pointer左侧(包括pointer)的元素处于递增顺序
・Pointer右侧的元素还没见过
这里写图片描述
注意:
如果左边第一个元素已经比pointer位置的小了,就不会继续进行比较了,因为pointer左侧的元素已经处于递增的顺序。

3.1 Insertion Sort:Java实现

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 */ }
}

3.2 Insersion Sort复杂度分析

从左向右依次移动pointer,然后将pointer与左侧元素进行比较,如果比左侧元素小两者就交换,然后继续和新位置的左侧元素比较,因此复杂度取决于输入。
- 最好情况(输入已经是升序):
每次pointer只需比较一次,不需要交换位置,因此共N次比较,0次交换
- 最坏情况(输入是降序):
每次pointer都要与左侧所有元素比较一次,并且要与每个元素都要交换一次位置, 0+1++N1=N(N1)2 ,即~ N22 次比较,~ N22 次交换

4. Shell Sort

想法:
因为insertion sort想要达到最终位置需要一次交换一个位置,通过h-sort来一次移动多个位置,并不断降低h。
如何h-sort?
以stride length h来进行insertion sort
这里写图片描述

A g-sorted array remains g-sorted after h-sorting it.

4.1 Shell Sort:Java实现

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 */ }
}

4.2 Shell Sort复杂度分析

The worst-case number of compares used by shellsort with
the 3x+1 increments is O(N3/2) .

5. Shuffling

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);
        }
    }
}

6. Convex hull

定义:
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的极角是依次变大的
这里写图片描述

6.1 Graham scan

・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.

判断三个点是否逆时针
这里写图片描述

猜你喜欢

转载自blog.csdn.net/Cyril__Li/article/details/79830263