排序算法

2020-05-13  本文已影响0人  王家磊

本篇文章参考《算法(第四版)》以下为文章的整体结构,方便浏览,也方便我以后回忆。

排序.png

初级排序算法

游戏规则

我们以数组为源数据,将他们按照顺序排列好。以下为对应算法的模板。
排序算法类的模板

public class Example
{
    public static void sort(Comparable[] a){}
    private static boolean less(Comparable v, Comparable w)
    {return v.compareTo() <0;}
    private static void exch(Comparable[] a, int i, int j)
    {Comparable t = a[i]; a[i] = a[j];a[j]= t;}
    private static void show(Comparable[] a)
    {
        for(int i = 0; i< a.length; i++)
            StdOut.print(a[i] + " ");
        StdOut.println();
    }
    public static boolean isSorted(Comarable[] a)
    {
        for(int i = 1; i< a.length; i++)
            if(less(a[i], a[i-1])) return false;
        return true;
    }
    public static void main(String[] args){
        String[] a = In.readStrings();
        sort(a);
        assert isSorted(a);
        show(a);
    }
}

在大多数情况下,排序的代码智慧通过两个方法操作数据:less() 方法对元素进行比较,exch() 方法将元素交换位置。isSorted()判断是否完成排序。

额外的内存使用 : 排序算法的额外内存和运行时间同等重要。排序算法可以分成两类,除了函数调用所需要的栈和固定数目的实例变量之外无需额外内存的原地排序算法,以及需要额外内存空间来存储另一份数组副本的其他排序算法。

选择排序

public class Selection
{
    public static void sort(Comparable[] a)
    {  // 将a[] 按升序排列
        int N = a.length;    // 数组长度
        for(int i = 0; i< N; i++){  // 将a[i] 和 a[i+1.. N] 中最小元素交换
            int min = i;    // 最小元素的索引
            for(int j = i+1; j< N; j++)
                if(less(a[j], a[min])) min =j;
            exch(a,i, min);
        }
    }
}

总的来说:排序算法是一种很容易理解和实现的简单排序算法,它有两个很鲜明的特点。

命题A: 对于长度为N 的数组,选择排序需要大约 N^2 /2 次比较和 N 次交换。

插入排序

public class Insertion
{
    public static void sort(Comparable[] a)
    {
        int N = a.length;
        for(int i = 1; i< N; i++)
        {
            for(int j = i; j > 0 && less(a[j], a[j-1]); j--)
                exch(a,j,j-1);
        }
    }
}

下面是几种典型的部分有序的数组:

命题B 对于随机排列的长度为N且主键不重复的数组,平均情况下插入排序需要 ~ N^2 /4 次比较以及 ~ N^2 /4 次交换。最坏情况下需要 ~N^2/2 次比较和 ~ N^2/2 最好的情况需要 N-1 次比较和0 次交换。
插入排序需要的交换操作和数组中倒置的数量相同,需要的比较次数大于等于倒置的数量,小于等于倒置的数量加上数组的大小再减一。

比较两个算法

对于随机排序的无重复主键的数组,插入排序和选择排序的运行时间是平方级别的,两者之比应该是一个较小的常熟。

希尔排序

希尔排序的思想是一个 h 有序数组就是 h 个互相独立的有序数组编织在一起组成一个数组。

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,i,j-h);
            }
            h = h/3;
        }
    }
}

归并排序

要将一个数组排序,可以先将它分成两半分别排序,然后将结果归并起来。

快速排序

命题K: 将长度为 N 的无重复数组排序,快速排序平均需要 ~2NlnN次比较

命题L: 快速排序最多约 N^2 次比较,但是随机打乱数组能够预防这种情况。

优先队列

上一篇 下一篇

猜你喜欢

热点阅读