zoukankan      html  css  js  c++  java
  • 几种常见的排序算法

    一.选择排序

      在待排序的一组数据中,选出最小(最大)的一个数与第一个位置的数交换,然后在剩下的数中,再找最小(最大)的数与第二个位置的数交换位置,依次类推,直到第N-1个元素与第N个元素交换位置,选择排序结束。

    import edu.princeton.cs.algs4.StdIn;
    import edu.princeton.cs.algs4.StdOut;
    import java.util.Comparator;
    
    public class Selection {
    
        private 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);
                assert isSorted(a, 0, i);
            }
            assert isSorted(a);
        }
    
        //使用比较器按升序重新排列数组
        public static void sort(Object[] a, Comparator comparator) {
            int n = a.length;
            for (int i = 0; i < n; i++) {
                int min = i;
                for (int j = i+1; j < n; j++) {
                    if (less(comparator, a[j], a[min])) min = j;
                }
                exch(a, i, min);
                assert isSorted(a, comparator, 0, i);
            }
            assert isSorted(a, comparator);
        }
    
    
        //对元素进行比较
        private static boolean less(Comparable v, Comparable w) {
            return v.compareTo(w) < 0;
        }
    
        // 对元素进行比较
        private static boolean less(Comparator comparator, Object v, Object w) {
            return comparator.compare(v, w) < 0;
        }
    
    
        // 交换两个数据
        private static void exch(Object[] a, int i, int j) {
            Object swap = a[i];
            a[i] = a[j];
            a[j] = swap;
        }
    
        // 检查数组是否已排序-对调试有用。
        private static boolean isSorted(Comparable[] a) {
            return isSorted(a, 0, a.length - 1);
        }
    
        // 判断从lo到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;
        }
    
        private static boolean isSorted(Object[] a, Comparator comparator) {
            return isSorted(a, comparator, 0, a.length - 1);
        }
    
        private static boolean isSorted(Object[] a, Comparator comparator, int lo, int hi) {
            for (int i = lo + 1; i <= hi; i++)
                if (less(comparator, a[i], a[i-1])) return false;
            return true;
        }
    
        //输出元素
        private static void show(Comparable[] a) {
            for (int i = 0; i < a.length; i++) {
                StdOut.println(a[i]);
            }
        }
    
        public static void main(String[] args) {
            String[] a = StdIn.readAllStrings();
            Selection.sort(a);
            show(a);
        }
    }

    二.插入排序

    将一个记录插入到已排好序的序列中,从而得到一个新的有序序列(将序列的第一个数据看成是一个有序的子序列,然后从第二个记录逐个向该有序的子序列进行有序的插入,直至整个序列有序)

    package sort;
    
    import edu.princeton.cs.algs4.StdIn;
    import edu.princeton.cs.algs4.StdOut;
    import java.util.Comparator;
    
    public class Insertion {
    
        private 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);
                }
                assert isSorted(a, 0, i);
            }
            assert isSorted(a);
        }
    
        //对lo到hi的元素进行排序
        public static void sort(Comparable[] a, int lo, int hi) {
            for (int i = lo + 1; i < hi; i++) {
                for (int j = i; j > lo && less(a[j], a[j-1]); j--) {
                    exch(a, j, j-1);
                }
            }
            assert isSorted(a, lo, hi);
        }
    
        //使用比较器按升序重新排列数组
        public static void sort(Object[] a, Comparator comparator) {
            int n = a.length;
            for (int i = 1; i < n; i++) {
                for (int j = i; j > 0 && less(a[j], a[j-1], comparator); j--) {
                    exch(a, j, j-1);
                }
                assert isSorted(a, 0, i, comparator);
            }
            assert isSorted(a, comparator);
        }
    
        public static void sort(Object[] a, int lo, int hi, Comparator comparator) {
            for (int i = lo + 1; i < hi; i++) {
                for (int j = i; j > lo && less(a[j], a[j-1], comparator); j--) {
                    exch(a, j, j-1);
                }
            }
            assert isSorted(a, lo, hi, comparator);
        }
    
        public static int[] indexSort(Comparable[] a) {
            int n = a.length;
            int[] index = new int[n];
            for (int i = 0; i < n; i++)
                index[i] = i;
    
            for (int i = 1; i < n; i++)
                for (int j = i; j > 0 && less(a[index[j]], a[index[j-1]]); j--)
                    exch(index, j, j-1);
    
            return index;
        }
    
        //对元素进行比较
        private static boolean less(Comparable v, Comparable w) {
            return v.compareTo(w) < 0;
        }
    
        private static boolean less(Object v, Object w, Comparator comparator) {
            return comparator.compare(v, w) < 0;
        }
    
        // 交换两个数据
        private static void exch(Object[] a, int i, int j) {
            Object swap = a[i];
            a[i] = a[j];
            a[j] = swap;
        }
    
        private static void exch(int[] a, int i, int j) {
            int swap = a[i];
            a[i] = a[j];
            a[j] = swap;
        }
    
        // 检查数组是否已排序-对调试有用。
        private static boolean isSorted(Comparable[] a) {
            return isSorted(a, 0, a.length);
        }
    
        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;
        }
    
        private static boolean isSorted(Object[] a, Comparator comparator) {
            return isSorted(a, 0, a.length, comparator);
        }
    
        private static boolean isSorted(Object[] a, int lo, int hi, Comparator comparator) {
            for (int i = lo + 1; i < hi; i++)
                if (less(a[i], a[i-1], comparator)) return false;
            return true;
        }
    
        private static void show(Comparable[] a) {
            for (int i = 0; i < a.length; i++) {
                StdOut.println(a[i]);
            }
        }
    
        public static void main(String[] args) {
            String[] a = StdIn.readAllStrings();
            Insertion.sort(a);
            show(a);
        }
    }

    三.希尔排序

    希尔排序的思想是使数组中任意间隔为h的元素都是有序的。这样的数组被称为h有序数组。换句话说,一个h有序数组就是h个互相独立的有序数组编制在一起组成的一个数组(如下图)。在进行排序的时候,如果h很大,我们能够将元素移动到很远的地方,为了实现更小的h有序创造方便,用这种方式,对于任意以1结尾的h序列,我们都能够将数组排序,这就是希尔排序。

    package sort;
    
    import edu.princeton.cs.algs4.StdIn;
    import edu.princeton.cs.algs4.StdOut;
    
    public class Shell {
    
        private Shell() { }
    
        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, 121, 364, 1093, ...
            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);
                    }
                }
                assert isHsorted(a, h);
                h /= 3;
            }
            assert isSorted(a);
        }
    
        // 比较两个元素
        private static boolean less(Comparable v, Comparable w) {
            return v.compareTo(w) < 0;
        }
    
        // 交换 a[i] 和 a[j]
        private static void exch(Object[] a, int i, int j) {
            Object swap = a[i];
            a[i] = a[j];
            a[j] = swap;
        }
    
        //判断是否有序
        private static boolean isSorted(Comparable[] a) {
            for (int i = 1; i < a.length; i++)
                if (less(a[i], a[i-1])) return false;
            return true;
        }
    
        // 判断从h开始是否有序
        private static boolean isHsorted(Comparable[] a, int h) {
            for (int i = h; i < a.length; i++)
                if (less(a[i], a[i-h])) return false;
            return true;
        }
    
        // 输出元素
        private static void show(Comparable[] a) {
            for (int i = 0; i < a.length; i++) {
                StdOut.println(a[i]);
            }
        }
    
        public static void main(String[] args) {
            String[] a = StdIn.readAllStrings();
            Shell.sort(a);
            show(a);
        }
    }

    四.归并排序

    1.自顶向下的归并排序

    package sort;
    
    import edu.princeton.cs.algs4.StdIn;
    import edu.princeton.cs.algs4.StdOut;
    
    public class Merge {
    
        private Merge() { }
    
        //排序函数
        public static void sort(Comparable[] a) {
            Comparable[] aux = new Comparable[a.length];
            sort(a, aux, 0, a.length-1);
            assert isSorted(a);
        }
    
        private static void sort(Comparable[] a, Comparable[] aux, int lo, int hi) {
            if (hi <= lo) return;
            int mid = lo + (hi - lo) / 2;
            sort(a, aux, lo, mid);
            sort(a, aux, mid + 1, hi);
            merge(a, aux, lo, mid, hi);
        }
    
        private static void sort(Comparable[] a, int[] index, int[] aux, int lo, int hi) {
            if (hi <= lo) return;
            int mid = lo + (hi - lo) / 2;
            sort(a, index, aux, lo, mid);
            sort(a, index, aux, mid + 1, hi);
            merge(a, index, aux, lo, mid, hi);
        }
    
        //合并两个有序数组
        private static void merge(Comparable[] a, Comparable[] aux, int lo, int mid, int hi) {
            // precondition: a[lo .. mid] and a[mid+1 .. hi] are sorted subarrays
            assert isSorted(a, lo, mid);
            assert isSorted(a, mid+1, hi);
    
            // copy to aux[]
            for (int k = lo; k <= hi; k++) {
                aux[k] = a[k];
            }
    
            // merge back to a[]
            int i = lo, j = mid+1;
            for (int k = lo; k <= hi; k++) {
                if      (i > mid)              a[k] = aux[j++];
                else if (j > hi)               a[k] = aux[i++];
                else if (less(aux[j], aux[i])) a[k] = aux[j++];
                else                           a[k] = aux[i++];
            }
    
            // postcondition: a[lo .. hi] is sorted
            assert isSorted(a, lo, hi);
        }
    
        private static void merge(Comparable[] a, int[] index, int[] aux, int lo, int mid, int hi) {
    
            // copy to aux[]
            for (int k = lo; k <= hi; k++) {
                aux[k] = index[k];
            }
    
            // merge back to a[]
            int i = lo, j = mid+1;
            for (int k = lo; k <= hi; k++) {
                if      (i > mid)                    index[k] = aux[j++];
                else if (j > hi)                     index[k] = aux[i++];
                else if (less(a[aux[j]], a[aux[i]])) index[k] = aux[j++];
                else                                 index[k] = aux[i++];
            }
        }
    
        //v < w ?
        private static boolean less(Comparable v, Comparable w) {
            return v.compareTo(w) < 0;
        }
    
        //判断数组是否有序
        private static boolean isSorted(Comparable[] a) {
            return isSorted(a, 0, a.length - 1);
        }
    
        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;
        }
    
        public static int[] indexSort(Comparable[] a) {
            int n = a.length;
            int[] index = new int[n];
            for (int i = 0; i < n; i++)
                index[i] = i;
    
            int[] aux = new int[n];
            sort(a, index, aux, 0, n-1);
            return index;
        }
    
        //输出元素
        private static void show(Comparable[] a) {
            for (int i = 0; i < a.length; i++) {
                StdOut.println(a[i]);
            }
        }
    
        public static void main(String[] args) {
            String[] a = StdIn.readAllStrings();
            Merge.sort(a);
            show(a);
        }
    }

    2.自底向上的归并排序

    package sort;
    
    import edu.princeton.cs.algs4.StdIn;
    import edu.princeton.cs.algs4.StdOut;
    
    public class MergeBU {
    
        private MergeBU() { }
    
        // stably merge a[lo..mid] with a[mid+1..hi] using aux[lo..hi]
        private static void merge(Comparable[] a, Comparable[] aux, int lo, int mid, int hi) {
    
            // copy to aux[]
            for (int k = lo; k <= hi; k++) {
                aux[k] = a[k];
            }
    
            // merge back to a[]
            int i = lo, j = mid+1;
            for (int k = lo; k <= hi; k++) {
                if      (i > mid)              a[k] = aux[j++];  // this copying is unneccessary
                else if (j > hi)               a[k] = aux[i++];
                else if (less(aux[j], aux[i])) a[k] = aux[j++];
                else                           a[k] = aux[i++];
            }
    
        }
    
        /**
         * Rearranges the array in ascending order, using the natural order.
         * @param a the array to be sorted
         */
        public static void sort(Comparable[] a) {
            int n = a.length;
            Comparable[] aux = new Comparable[n];
            for (int len = 1; len < n; len *= 2) {
                for (int lo = 0; lo < n-len; lo += len+len) {
                    int mid  = lo+len-1;
                    int hi = Math.min(lo+len+len-1, n-1);
                    merge(a, aux, lo, mid, hi);
                }
            }
            assert isSorted(a);
        }
    
        // is v < w ?
        private static boolean less(Comparable v, Comparable w) {
            return v.compareTo(w) < 0;
        }
    
    
        /***************************************************************************
         *  Check if array is sorted - useful for debugging.
         ***************************************************************************/
        private static boolean isSorted(Comparable[] a) {
            for (int i = 1; i < a.length; 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++) {
                StdOut.println(a[i]);
            }
        }
    
        public static void main(String[] args) {
            String[] a = StdIn.readAllStrings();
            MergeBU.sort(a);
            show(a);
        }
    }

    五.快速排序

    它的基本思想是:选择一个基准数,通过一趟排序将要排序的数据分割成独立的两部分;其中一部分的所有数据都比另外一部分的所有数据都要小。然后,再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。

    1.快速排序

    package sort;
    
    import edu.princeton.cs.algs4.StdIn;
    import edu.princeton.cs.algs4.StdOut;
    import edu.princeton.cs.algs4.StdRandom;
    
    public class Quick {
    
        private Quick() { }
    
        //使用自然顺序按升序重新排列数组。
        public static void sort(Comparable[] a) {
            StdRandom.shuffle(a);
            sort(a, 0, a.length - 1);
            assert isSorted(a);
        }
    
        // 排序 a[lo] 到 a[hi]的元素
        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);
            assert isSorted(a, lo, hi);
        }
    
        // 分区子阵列a[lo..hi],使a[lo..j-1]<=a[j]<=a[j+1..hi]
        private static int partition(Comparable[] a, int lo, int hi) {
            int i = lo;
            int j = hi + 1;
            Comparable v = a[lo];
            while (true) {
                // 查找左边需要交换的元素
                while (less(a[++i], v)) {
                    if (i == hi) break;
                }
                // 查找右边需要交换的元素
                while (less(v, a[--j])) {
                    if (j == lo) break;
                }
                if (i >= j) break;
                exch(a, i, j);
            }
            exch(a, lo, j);
            return j;
        }
    
        //重新排列数组,使{@code a[k]}包含第k个最小键;
        public static Comparable select(Comparable[] a, int k) {
            if (k < 0 || k >= a.length) {
                throw new IllegalArgumentException("index is not between 0 and " + a.length + ": " + k);
            }
            StdRandom.shuffle(a);
            int lo = 0, hi = a.length - 1;
            while (hi > lo) {
                int i = partition(a, lo, hi);
                if      (i > k) hi = i - 1;
                else if (i < k) lo = i + 1;
                else return a[i];
            }
            return a[lo];
        }
    
        // is v < w ?
        private static boolean less(Comparable v, Comparable w) {
            if (v == w) return false;   // optimization when reference equals
            return v.compareTo(w) < 0;
        }
    
        // 交换 a[i] 和 a[j]
        private static void exch(Object[] a, int i, int j) {
            Object swap = a[i];
            a[i] = a[j];
            a[j] = swap;
        }
    
        //判断数组是否有序
        private static boolean isSorted(Comparable[] a) {
            return isSorted(a, 0, a.length - 1);
        }
    
        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;
        }
    
        //输出数组
        private static void show(Comparable[] a) {
            for (int i = 0; i < a.length; i++) {
                StdOut.println(a[i]);
            }
        }
    
        public static void main(String[] args) {
            String[] a = StdIn.readAllStrings();
            Quick.sort(a);
            show(a);
            assert isSorted(a);
    
            StdRandom.shuffle(a);
    
            StdOut.println();
            for (int i = 0; i < a.length; i++) {
                String ith = (String) Quick.select(a, i);
                StdOut.println(ith);
            }
        }
    
    }

    2.三向切分的快速排序

    package sort;
    
    import edu.princeton.cs.algs4.StdIn;
    import edu.princeton.cs.algs4.StdOut;
    import edu.princeton.cs.algs4.StdRandom;
    
    public class Quick3way {
    
        private Quick3way() { }
    
        public static void sort(Comparable[] a) {
            StdRandom.shuffle(a);
            sort(a, 0, a.length - 1);
            assert isSorted(a);
        }
    
        private static void sort(Comparable[] a, int lo, int hi) {
            if (hi <= lo) return;
            int lt = lo, gt = hi;
            Comparable v = a[lo];
            int i = lo + 1;
            while (i <= gt) {
                int cmp = a[i].compareTo(v);
                if      (cmp < 0) exch(a, lt++, i++);
                else if (cmp > 0) exch(a, i, gt--);
                else              i++;
            }
    
            // a[lo..lt-1] < v = a[lt..gt] < a[gt+1..hi].
            sort(a, lo, lt-1);
            sort(a, gt+1, hi);
            assert isSorted(a, lo, hi);
        }
    
        // is v < w ?
        private static boolean less(Comparable v, Comparable w) {
            return v.compareTo(w) < 0;
        }
    
        // 交换 a[i] 和 a[j]
        private static void exch(Object[] a, int i, int j) {
            Object swap = a[i];
            a[i] = a[j];
            a[j] = swap;
        }
    
        //判断数组是否有序
        private static boolean isSorted(Comparable[] a) {
            return isSorted(a, 0, a.length - 1);
        }
    
        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;
        }
    
    
    
        // 输出数组
        private static void show(Comparable[] a) {
            for (int i = 0; i < a.length; i++) {
                StdOut.println(a[i]);
            }
        }
    
        public static void main(String[] args) {
            String[] a = StdIn.readAllStrings();
            Quick3way.sort(a);
            show(a);
        }
    
    }

    六.堆排序

    堆是具有以下性质的完全二叉树:每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆;或者每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆。

    大顶堆

     

    小顶堆

     

    算法演示

     
    package sort;
    
    import edu.princeton.cs.algs4.StdIn;
    import edu.princeton.cs.algs4.StdOut;
    
    public class Heap {
    
        private Heap() { }
    
        public static void sort(Comparable[] pq) {
            int n = pq.length;
            for (int k = n/2; k >= 1; k--)
                sink(pq, k, n);
            while (n > 1) {
                exch(pq, 1, n--);
                sink(pq, 1, n);
            }
        }
    
        //下沉
        private static void sink(Comparable[] pq, int k, int n) {
            while (2*k <= n) {
                int j = 2*k;
                if (j < n && less(pq, j, j+1)) j++;
                if (!less(pq, k, j)) break;
                exch(pq, k, j);
                k = j;
            }
        }
    
        //比较
        private static boolean less(Comparable[] pq, int i, int j) {
            return pq[i-1].compareTo(pq[j-1]) < 0;
        }
    
        //交换
        private static void exch(Object[] pq, int i, int j) {
            Object swap = pq[i-1];
            pq[i-1] = pq[j-1];
            pq[j-1] = swap;
        }
    
        //输出元素
        private static void show(Comparable[] a) {
            for (int i = 0; i < a.length; i++) {
                StdOut.println(a[i]);
            }
        }
    
        public static void main(String[] args) {
            String[] a = StdIn.readAllStrings();
            Heap.sort(a);
            show(a);
        }
    }
  • 相关阅读:
    BZOJ5473: 仙人掌
    BZOJ5289: [Hnoi2018]排列
    BZOJ5322: [JXOI2018]排序问题
    BZOJ5323:[JXOI2018]游戏
    webstorm引用ESLint进行静态代码检查
    React基础知识
    静态资源优化方案
    Nodejs 饭店
    linux du和df
    Docker知识-1
  • 原文地址:https://www.cnblogs.com/wuwuyong/p/12269168.html
Copyright © 2011-2022 走看看