Algs4 - Sorting,排序算法

Sorting

Merge Sort

Implementation

Also see source code in Merge.java

  • Merger function, merge to sorted arrays.
private static void merge(Comparable[] a, Comparable[] aux, int lo, int mid, int hi) {
    assert isSorted(a, lo, mid);
    assert isSorted(a, mid+1, hi);
    // copy to auxiliary array
    for (int k = lo; k < hi; k++) {
        aux[k] = a[k];
    }
    // merge
    int i = lo, j = mid + 1;
    for (int k = lo; k < hi; k++) {
        if      (i > mid)              a[k] = aux[j++];
        else if (j > hi)               a[k] = aux[i++];
        else if (less(aux[j], aux[i])) a[k] = aux[j++];
        else                           a[k] = aux[i++];
    }
}
  • Class Merge, perform sort and merge
private class Merge {
    private static void merge(...) { /* as before */}

    private static void sort(Comparable[] a, Comparable[] aux, int lo, int hi) {
        if (hi <= lo) return;
        int mid = lo + (hi - lo) / 2;
        sort(a, aux, lo, mid);
        sort(a, aux, mid+1, hi);
        merge(a, aux, lo, mid, hi);
    }

    public static void sort(Comparable[] a) {
        aux = new Comparable[a.length];
        sort(a, aux, 0, a.length - 1);
    }
}
  • Bottom-up mergesort: Java implementation
public class MergeBU {
    private static void merge(...) {...}

    private static void sort(Comparable[] a) {
        int N = a.length;
        Comparable[] aux = new Comparable[N];
        for (int sz = 1; sz < N; sz = sz+sz) { 
        // array size 从 1 开始, 每次 merge 完之后 size 翻倍
            for (int lo = 0; lo < N-sz; lo += sz+sz) 
            // two array of size sz merge together, then go to the next two sub-array, until the end of array.
                merge(a, aux, lo, lo+sz-1, Math.min(lo+sz+sz-1, N-1)));
        }
    }
}
  • Practical improvements
    • Use insertion sort for small subarrays
    • Stop if already sorted
      • Is biggest item in first half <= smallest item in second half?
      • Helps for partially-ordered arrays.
    • Eliminate the copy to the auxiliary array. Save time (but not space).

Comparators

  • Comparable interface: sort using a type’s natural order.

  • Comparator interface: sort using an alternate order (Must be a total order)

    public interface Comparator<Key>
      int compare(Key v, Key w)    // compare keys v and w
    
  • To implement a comparator:

    • Define a (nested) class that implements the Comparator interface.
    • Implement the compare() method.

Example: Point2D.java

Stability

A typical application: First, sort by name, then sort by section.
A stable sort preserves the relative order of items with equal keys.
Stable: Insertion, Merge Sort Unstable: Selection, Shell, Quick Sort

Quick Sort

Implementation

Choose a sentinel and partition the array, also see in Quick.java

private static int partition(Comparable[] a, int lo, int hi) {
    int i = lo, j = hi+1;
    while (true) {
        while (less(a[++i], a[lo])) // 如果a[i]小于sentinel,++i
            if (i == hi) break;
        while (less(a[lo], a[--j])) // 如果a[j]小于sentinel,--j
            if (j == lo) break;

        if (i >= j) break;   // i and j cross, exit loop
        exch(a, i, j);       // exchange a[i] and a[j]
    }
    exch(a, lo, j);    // exchange a[lo](sentinel) and a[j]
    return j;
}

Quick Sort class

public class Quick {
    private static int partition(Comparable[] a, int lo, int hi) { ... }

    public static void sort(Comparable[] a) {
        StdRandom.shuffle(a);
        sort(a, 0, a.length - 1);
    }

    private static void sort(Comparable[] a, int lo, int hi) {
        if (hi <= lo) return;
        int j = partition(a, lo, hi);
        sort(a, lo, j-1);  // a[j] is sentinel
        sort(a, j+1, hi);
    }
}

Selection: Find the kth smallest item in an array

public static Comparable select(Comparable[] a, int k) {
    StdRandom.shuffle(a);
    int lo = 0, hi = a.length - 1;
    while (hi > lo) {
        int j = partition(a, lo, hi);
        if (j < k) lo = j + 1;
        if (j > k) hi = j - 1;
        else return a[k];
    }
    return a[k];
}

3-way Quicksort

The goal of 3-way partitioning is to speed up quicksort in the presence of duplicate keys.

  • Quicksort with 3-way partitioning is entropy-optimal. (Proof: beyond scope)
  • Bottom line: Randomized quicksort with 3-way partitioning reduces running time from linearithmic to linear in broad class of applications. Best case N, average NlgN, worst N^2/2
private static void sort(Comparable[] a, int lo, int hi) {
    if (hi <= lo) return;
    int lt = lo, gt = hi;
    Comparable v = a[lo];
    int i = lo;
    while (i < gt) {
        int cmp = a[i].compareTo(v);
        if (cmp < 0) exch(a, lt++, i++);
        else if (cmp > 0) exch(a, i, gt--);
        else i++;
    }
    sort(a, lo, lt-1);
    sort(a, gt+1, hi);
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HK697lrb-1585967019425)(…/…/.gitbook/assets/3-way.png)]

Also see source code in Quick3way.java

System Sorts

  • Java Arrays.sort() uses tuned quicksort for primitive types; tuned mergesort for objects.

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pce0T5qx-1585967019427)(…/…/.gitbook/assets/sortsummary.png)]

Collinear Points (Exercise)

For each point, calculate the slop of this point and every other points, sort these points by slope order. The points with equal slopes are collinear points.

Specification
Solution

Heap Sort

Heap-ordered binary tree

  • Keys in nodes
  • Parent’s key no smaller than children’s key

Array representation

  • Indices start at 1.
  • Take nodes in level order
  • No explicit links needed!

Use array indices to move through tree, parent node at k is at k/2, children of node at k are at 2k and 2k+1.

Binary heap: Java implementation, also see in MaxPQ.java

public class MaxPQ<Key extends Comparable<Key>> {
    private Key[] pq;  // store items at indices 1 to n
    private int N;  // number of items on priority queue

    public MaxPQ(int capacity) {
        pq = (Key[]) new Comparable[capacity];
    }
    public boolean isEmpty() { return N == 0; }
    public void insert(Key x) { 
        if (n == pq.length - 1) resize(2 * pq.length);
        pq[++N] = x; 
        swim(N);
    }
    public Key delMax() {
        Key max = pq[1];
        exch(1, N--);
        sink(1);
        pq[N+1] = null;  // prevent loitering
        return max;
    }
    private void sink(int k) { // sink node k
        while (2*k <= N) {
            // left child of node k is 2*k, right child of node k is 2*k+1
            int j = 2*k; 
            // if left child is less than right child, move to right child
            if (j < n && less(j, j+1)) j++; 
            // if parent node is greater than the larger child, then break while
            if (!less(k,j)) break;
            // else, parent node is smaller than child j, exch them
            exch(k, j);
            // follow the node, go to the next level
            k = j; 
        }
    }
    private void swim(int k) { // swim node k
        // while parent node is smaller than node k, then swap these two items.
        while (k > 1 && less(k/2, k)) {
            exch(k, k/2);
            k = k/2;
        }
    }
}

Heapsort: basic plan for in-place sort, see source code Heap.java

  • Create max-heap with all N keys
  • Repeatedly remove the maximum key
public class Heap {
    public static void sort(Comparable[] a) {
        int N = a.length;
        // construct the heap order, from the last parent node to k = 1.
        for (int k = N/2; k>=1; k--) 
            sink(a, k, N);
        // exchange the max with the end of array, sink a[1], get rid of sorted part.
        while (N > 1) {
            exch(a, 1, N);
            sink(a, 1, --N);
        }
    }
}

Significance. In-place sorting algorithm with NlogN worst-case.
Bottom line: Heapsort is optimal for both time and space, but

  • Inner loop longer than quick sort
  • Makes poor use of cache memory, references to memory are all over the place when it is a huge array. So it is not a good alg for situation with caching. Does not have local memory address, but quick sort has.
  • Not stable

Event-Driven Simulation (optional)

Predict the collision events, add these events to the priority queue (initialization), dequeue the event within minimum time, and then update the velocity of collision points, predict events correspond to the updated points, add the new predicted event to priority queue, repeat and simulate this process. see website Event-Driven Simulation

8-puzzle (Exercise)

Use A* search algorithm, the idea is: First, insert the initial search node (the initial board, 0 moves, and a null previous search node) into a priority queue. Then, delete from the priority queue the search node with the minimum priority, and insert onto the priority queue all neighboring search nodes (those that can be reached in one move from the dequeued search node). Repeat this procedure until the search node dequeued corresponds to the goal board.
Specification
Solution

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值