美文网首页
《算法》2.1-初级排序算法

《算法》2.1-初级排序算法

作者: 不会code的程序猿 | 来源:发表于2017-07-05 09:58 被阅读13次

    1. 基本规则

    1. 排序类算法模板
    public class Example
    {
        public static void sort(Comparable[] a)
        {
            /* See Algorithms 2.1, 2.2, 2.3, 2.4, 2.5, or 2.7. */ }
    
        private static boolean less(Comparable v, Comparable w)
        {
            return v.compareTo(w) < 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)
        { // Print the array, on a single
            // line.
            for (int i = 0; i < a.length; i++)
                StdOut.print(a[i] + " ");
            StdOut.println();
        }
    
        public static boolean isSorted(Comparable[] a)
        { // Test whether the array
            // entries are in order.
            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)
        { // Read strings from standard
            // input, sort them, and print.
            String[] a = In.readStrings();
            sort(a);
            assert isSorted(a);
            show(a);
        }
    }
    
    1. Comparable接口
      实现了Comparable接口的数据类型:Integer、String、Double都实现了Comparable接口。创建自己的数据类型时,我们也要实现Comparable接口就能使用该模板进行排序。必须要实现Comparable接口中的compareTo方法。
    public class Date implements Comparable<Date>
    {
        private final int day;
        private final int month;
        private final int year;
        public Date(int d, int m, int y)
        {
            day = d;
            month = m;
            year = y;
        }
        public int day() {return day;}
        public int month(){return month;}
        public int year(){return year;}
        public int compareTo(Date that)
        {
            if (this.year > that.year)
                return +1;
            if (this.year < that.year)
                return -1;
            if (this.month > that.month)
                return +1;
            if (this.month < that.month)
                return -1;
            if (this.day > that.day)
                return +1;
            if (this.day < that.day)
                return -1;
            return 0;
        }
        public String toString()
        {
            return month + "/" + day + "/" + year;
        }
    }
    

    compareTo必须实现一个全序关系:
    ①自反性:对所有的v=v
    ②反对称性:对所有v<w都有v>w,且v=w时w=v
    ③传递性

    1. 排序成本模型:比较次数和访问数组的次数
    2. 额外的内存使用

    2. 选择排序

    1. 思想
      首先,找到数组中最小的元素,其次将它和数组的第一个元素交换位置。再次,在剩下的元素中找到最小的元素和数组的第二个元素交换位置。如此往复,直到将整个数组排序。不断选择剩余元素中的最小者。
    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(less(a[j],a[min])) min=j;
                exch(a,i,min);
            }
        }
    }
    
    1. Example

      选择排序
    2. 分析:
      ①运行时间和输入无关
      ②数据移动是最少的
      ③长度为N的数组需要交换N次,比较次数:(N-1)+(N-2)+...1=N(N-1)/2~![](http://chart.googleapis.com/chart?cht=tx&chl= N^2/2)

    3. 插入排序

    1. 思想
      想象打扑克牌,一张一张地把牌插入到适当地位置。在计算机的视线中,为了要给插入的元素腾出空间,我们需要将其余所有元素在插入之前都向后移动一位。插入排序所需要的时间取决于输入元素中的初始顺序。
    public class Insertion
    {
        public static void sort(Comparable[] a)
        {
            int N=a.length;
            for(int i=1;i<N;i++)
            {   //a[i]插入到a[i-1] a[i-2]...1中
                for(int j=i;j>=0&&less(a[j],a[j-1]);j--)
                {
                    exch(a,j,j-1);
                }
            }
        }
    }
    
    1. Example
      插入排序
    2. 分析:
      ①best:输入顺序增大,无需移动元素,只需要N-1次比较。
      ②worst:输入是逆序的:N2/2次比较和交换
      ③平均:N2/4次比较和交换

    4. 希尔排序

    1. 思想:
      基于插入排序的快速排序算法。对于大规模乱序的数组插入排序很慢,是因为它只会交换相邻的元素,因此元素只能一点一点移动。希尔排序改进了插入排序算法,交换不相邻的元素以对数组的局部进行排序,并最终用插入排序将局部有序的数组排序。 关键:使数组中任意间隔为h的元素都是有序的
    public static void sort(Comparable[] a) {
            int n = a.length;
            // 3x+1 increment sequence:  1, 4, 13, 40, 121, 364, 1093, ... 
            int h = 1;
            while (h < n/3) h = 3*h + 1; 
            while (h >= 1) {
                // h-sort the array
                for (int i = h; i < n; i++) {
                      //将a[i]插入到a[i-h],a[i-2*h],a[i-3*h].....
                    for (int j = i; j >= h && less(a[j], a[j-h]); j -= h) {
                        exch(a, j, j-h);
                    }
                }
                assert isHsorted(a, h); 
                h /= 3;
            }
            assert isSorted(a);
    }
    
    1. Example
      希尔排序
    2. 分析:
      希尔排序是基于插入排序的一种算法, 在此算法基础之上增加了一个新的特性,提高了效率。希尔排序的时间复杂度与增量序列的选取有关,希尔排序时间复杂度的下界是n*log2n。希尔排序没有快速排序算法快 O(n(logn)),因此中等大小规模表现良好,对规模非常大的数据排序不是最优选择。但是比O( n^2 )复杂度的算法快得多。并且希尔排序非常容易实现,算法代码短而简单。 此外,希尔算法在最坏的情况下和平均情况下执行效率相差不是很多,与此同时快速排序在最坏的情况下执行的效率会非常差。

    相关文章

      网友评论

          本文标题:《算法》2.1-初级排序算法

          本文链接:https://www.haomeiwen.com/subject/peifhxtx.html