常用算法总结

基于比较的排序算法的最优性能是O(n log n)

文中代码通用的两个方法:

private static boolean less(Comparable v, Comparable w)
{
    return v.compareTo(w) < 0;
}

private static void exch(Comparable[] a, int i, int j)
{
    Comparable swap = a[i];
    a[i] = a[j];
    a[j] = swap;
}

插入排序

  • Time Complexity: O(n ^ 2) 最好情况O(n)
  • 稳定
  • in place
public class Insertion
{
    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] < a[j - 1]) {
                    exch(a, j, j-1);
                }
                else
                    break;
    }
}

选择排序

  • Time Complexity: O(n ^ 2)
  • 不稳定
  • in place
public class Selection
{
    public static void sort(Comparable[] a)
    {
        int N = a.length;
        for (int i = 0; i < n; i++)
        {
            int min = i;
            for (int j = i + 1; j < N; j++)
                if (a[j] < a[min])
                    min = j;
            exch(a, i, min);
        }
    }
}

希尔排序

  • Time Complexity: O(n)
  • not stable
  • in palce
public class shell
{
    public static void sort(Comparable[] a)
    {
        int N = a.length;

        int h = 1;
        while (h < N/3)
            h = 3*h + 1;

        while (h >= 1)
        {
            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;
        }
    }
}

快速排序

  • Time Complexity: O(n log n) 最坏情况O(n ^ 2)
  • 不稳定
  • in place
public class Quick
{
    private static int partition(Comparable[] a, int lo, int hi)
    {
        int i = lo, j = hi + 1;
        while (true)
        {
            while(less(a[++i], a[lo]))
                if (i == hi) break;
            while(less(a[lo], a[--j]))
                if (j == lo) break;

            if (i >= j) break;
            exch(a, i, j);
        }

        exch(a, lo, j);
        return j; //return index of item new known to be in place
    }

    public static void sort(Comparable[] a, int lo, int hi)
    {
        StdRandom.shuffle(a); // for performance guarantee against worst case
        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);
        sort(a, j+1, hi);
    }
}

归并排序

  • Time Complexity: O(n log n)
  • 稳定
  • not in place, need extra space
public class Merge
{

    public static void sort(Comparable[] a)
    {
        Comparable[] aux = new Comparable[a.length];
        sort(a, aux, 0, a.length - 1);
    }

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

    private static void merge(Comparable[] a, Comparable[] aux, int lo, int mid, int hi)
    {
        for (int k = lo; k <= hi; k++)
            aux[k]= a[k];

        int i = lo; j = mid + 1;
        for (int k = lo; k <= hi; k++)
        {
            // if i is already greater than mid, that means the rest elements
            // is already in the final place
            if (i > mid)
                a[k] = aux[j++];
            else if (j > hi) // the same as above
                a[k] = aux[i++];
            else if (less(aux[j], aux[i]))
                a[k] = aux[j++];
            else
                a[k] = aux[i++];
        }
    }
}

基数排序

基数排序的思路很简单,是根据每一位上的数字对数据进行分组排序,最终合并。

  • Time Complexity: O(kn) k是数据中最大数的位数
  • 不稳定
  • not in place

堆排序

  • Time Complexity: O(n log n)
  • not stable
  • in place
public class Heap
{
    public static void sort(Comparable[] a)
    {
        int N = a.length;
        for (int k = N/2; k >= 1; k--)
            sink(a, k, N);
        while (N > 1)
        {
            exch(a, 1, N);
            sink(a, 1, --N);
        }
    }

    private static void sink(Comparable[] a, int k, int N)
    {
        while (2*k <= N)
        {
            int j = 2*k;
            if (j < N && less(j, j+1))
                j++;
            if (!less(k, j))
                break;
            exch(a, k, j);
            k = j;
        }
    }
}
comments powered by Disqus