• 排序算法


    选择排序

    定义:每次迭代过程中,我们都是从剩余元素(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++];
              }
         }
    }

    高速排序











  • 相关阅读:
    解决跨域问题的后端解决方案
    java-反射
    验证接口实现类对于接口中所有方法是否都要重写?
    完成Triangle时遇到的问题
    刚知道的一种算法
    完成ATM编程练习题时遇到的问题
    完成Account编程练习遇到的问题
    完成StopWatch编程练习题时遇到的一些问题
    Window环境下Java备份和恢复Mysql数据
    IDEA导入项目不下载依赖问题
  • 原文地址:https://www.cnblogs.com/wgwyanfs/p/6902333.html
Copyright © 2020-2023  润新知