排序算法

选择排序

定义:每次迭代过程中,我们都是从剩余元素(remaining entries)中选得最小的元素放在对应的位置上,这里的不变量(invariant)为左边已经排好序的部分。
特点:比較次数是 N(N-1)/2  交换次数是 N (each exchange puts an item into its final position, so the number of exchanges is N. Thus, the running time is dominated by the number of compares)。数学模型是上三角。每一次寻找最小元素的过程不会为下一趟的寻找提供额外信息。所以对于一个有序的数组。仍然要花和一个随机数组一样长的时间;选择排序中数组訪问是和数组尺寸线性相关的,这是其它排序不具有的。
实现
public class SelectionSort {

     // This class should not be instantiated.
     private SelectionSort() {
     }

     // ascending order
     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);
               assert isSorted(a, 0, i);
          }
           assert isSorted(a);
     }

     /***********************************************************************
      * Helper sorting functions
      ***********************************************************************/

     // is v < w ?

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

     // exchange a[i] and a[j]
     private static void exch(Object[] a, int i, int j) {
          Object swap = a[i];
          a[i] = a[j];
          a[j] = swap;
     }

     /***********************************************************************
      * Check if array is sorted - useful for debugging
      ***********************************************************************/
     // is the array a[] sorted?

     private static boolean isSorted(Comparable [] a) {
           return isSorted(a, 0, a. length - 1);
     }

     // is the array sorted from a[lo] to a[ hi]
     private static boolean isSorted(Comparable [] a, int lo, int hi) {
           for (int i = lo + 1; i <= hi; i++)
               if (less(a[i], a[i - 1]))
                    return false ;
           return true ;
     }

     // print array to standard output
     private static void show(Comparable[] a) {
           for (int i = 0; i < a.length; i++) {
              System. out.print(a[i] + " " );
          }
     }

     public static void main(String[] args) {
          Integer[] a = { 10, 45, 0, 8, 7, -34, 20 };
          SelectionSort. sort(a);
           show(a);
     }
}

插入排序

定义:能够联系到扑克牌,每次都是将一个数字插入到一个有序序列的合适位置。为了给其腾出空间。须要后移比他大的元素。
特点:尽管在当前元素(current index)左边都是有序的,可是却不是他们的终于位置;对于一个随机数组,如果每次在插入一个元素时都是移动一半。则#compare=N^2/4。#exchange=N^2/4。最坏情况是每次都是插入到第一个位置(和选择排序一样了)是N^2/2。最好情况是已经有序,仅仅须要比較N-1次。
假设数组中倒置的数量小于数组大小的常数倍数,那么称这种数组是部分有序的。插入排序对于这种数组非常有效。(倒置是一个序列中乱序的键值对的个数,比方AEDC中的倒置有E-D,E-C,D-C,也就是须要变换位置的pair)
实现
public class InsertionSort {
      //其它代码同上
     // ascending order
     public static void sort(Comparable[] a) {
           int N = a.length ;
           for (int i = 0; i < N; i++) {
               for (int j = i; j > 0 && less (a[j], a[j - 1]); j--) {
                    exch(a, j, j - 1);
              }
          }
     }
}

希尔排序

定义:对于大规模乱序数组插入排序非常慢,由于它仅仅交换相邻的元素。所以元素仅仅能一步步的从这一端移动到还有一端;希尔排序在插入排序的基础上做了改进。先对几个交错的序列进行局部排序(比方步长是h的子数组)这样加快了元素交换的速度,没一次的h-sort都会使得数组越来越有序,然后逐渐改变增长序列。直到终于得到有序数组。希尔排序在数组的尺寸和部分有序直接做了权衡。部分有序的程度取决于增长序列。
特点至今没有发现一个最优的增量序列,使用递增序列(3x+1) 1, 4, 13, 40, 121, 364…的希尔排序所需的比較次数不会超出 N 的若干倍乘以递增序列的长度。

在这个增量序列下。shellsort最多比較次数是N^(3/2).
实现
public class ShellSort {

     // This class should not be instantiated.
     private ShellSort() {
     }

     // ascending order
     public static void sort(Comparable[] a) {
           int N = a.length ;
           int h = 1;
           // 找到最大的步长
           while (h < N / 3)
               h = 3 * h + 1; // 1,4,13,40
           while (h >= 1) {
               // 用不同的增量来对子数组插入排序
               for (int i = h ; i < N; i += h) {
                    for (int j = i; j > 0 && less (a[j], a[j - h]); j -= h ) {
                         exch(a, j, j - h );
                   }
              }
               h /= 3;
          }
     }
}

Shuffle Sort

这里是利用排序的场景,洗牌算法
1.为每一张牌随机产生不同的数,而后利用上述的排序算法;
2.In iteration i, pick integer r between 0 and i uniformly at random. then Swap a[i] and a[r].(这是Knuth发明的)显然是线性复杂度。
实现:
public class TestShuffle {

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

      public static void shuffle( int[] a) {
           int N = a.length ;
           for (int i = 0; i < N; i++) {
               int r = StdRandom.uniform(i + 1); // 在 1-i之间产生随机数
               exch(a, i, r);
          }
     }

      public static void main(String[] args) {
           int [] test = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
           shuffle(test);
           for (int i = 0; i < test. length; i++)
              System. out .print(test[i] + " " );
     }
}

归并排序

定义:利用分治思想,将大问题划分为小问题,然后进行合并。
特点:最大的长处是NlgN的复杂度(能够通过公式推导,或画递归树得到)
实现
public class MergeSort {
     private static Comparable[] aux; // 辅助数组

     // This class should not be instantiated.
     private MergeSort() {
     }

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

     // 递归子例程
     private static void sort(Comparable[] a, int lo, int hi) {
           if (hi <= lo)
               return;
           int mid = lo + (hi - lo) / 2;
           sort(a, lo, mid);
           sort(a, mid + 1, hi);
           merge(a, lo, mid, hi);
     }
      // in-place merge , not to get an output array
     public static void merge(Comparable[] a, int lo, int mid, int hi) {
           int i = lo, j = mid + 1, k;
           for (k = lo; k <= hi; k++)
               aux[k] = a[k];
           // merge back to the original array a[lo.....hi]
           for (k = lo; k <= hi; k++) {
               if (i > mid) // left is over
                   a[k] = aux[j++];
               else if (j > hi) // right is over
                   a[k] = aux[i++];
               else if (less( aux[i], a[j]))
                   a[k] = aux[i++];
               else
                   a[k] = a[j++];
          }
     }
}

高速排序











posted on 2017-05-25 10:17  wgwyanfs  阅读(188)  评论(0)    收藏  举报

导航