zoukankan      html  css  js  c++  java
  • 排序算法

    package kunpu.arithmetic;
    
    /**
     * @author zhen
     * @Date 2018/3/29 17:06
     */
    public class GCD {
        /**
         * 欧几德算法
         * 计算两个非负整数p和q的最大公约数:若q是0,则最大公约数是p。否则,将p除以q得到余数r,p和q的最大公约数即为q和r的最大公约数
         */
        public int methodOne(int p, int q){
            if (q == 0){
                return p;
            }
            int r = p%q;
            return methodOne(q, r);
        }
    }
    
    
    package kunpu.arithmetic;
    
    /**
     * @author zhen
     * @Date 2018/4/2 9:31
     */
    public abstract class Sort {
        public static boolean less(Comparable a, Comparable b){
            return a.compareTo(b) < 0;
        }
    
        public static void exch(Comparable[] a, int i, int j){
            Comparable temp = a[i];
            a[i] = a[j];
            a[j] = temp;
        }
    
        public static boolean isSort(Comparable[] a){
            for(int i = 1; i < a.length; i++){
                if (less(a[i], a[i-1])){
                    return false;
                }
            }
            return true;
        }
    
        public abstract void sort(Comparable[] a);
    }
    
    
    package kunpu.arithmetic;
    
    /**
     * 插入排序
     * 规则:将每一个元素插入到已经有序数组的位置中
     * @author zhen
     * @Date 2018/4/2 9:47
     */
    public class Insertion extends Sort {
        @Override
        public void sort(Comparable[] a) {
            int N = a.length;
            for (int i = 1; i < N; i++){
                //元素处于J的位置;J之前的元素都是有序的;J一直前移直到动不了
                for(int j = i; j > 0 && less(a[j], a[j-1]); j--){
                    exch(a, j, j-1);
                }
            }
        }
    
    
    }
    
    
    package kunpu.arithmetic;
    
    /**
     * 归并排序 自顶向下的归并
     * 规则:将一个数组排序,现将它分为两半进行排序,然后将结果归并起来
     * @author zhen
     * @Date 2018/4/2 11:03
     */
    public class Merge extends Sort {
        Comparable[] aux;
    
        @Override
        public void sort(Comparable[] a) {
            aux = new Comparable[a.length];
            sort(a, 0, a.length - 1);
        }
    
        private 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, hi);
            if (less(a[mid + 1], a[mid])){
                merge(a, lo, mid, hi);
            }
    
        }
    
        public void merge(Comparable[] a, int lo, int mid, int hi){
            //将a[lo..mid]和a[mid+1...hi]归并
            int i = lo,
                j = mid + 1;
            for(int k = lo; k <= hi; k++){//将a[lo...hi复制到aux[lo...hi]
                aux[k] = a[k];
            }
            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++];
                }
            }
        }
    }
    
    
    package kunpu.arithmetic;
    
    /**
     * 自底而上的归并
     * @author zhen
     * @Date 2018/4/2 11:47
     */
    public class MergeBu extends Sort {
        Comparable[] aux;
        @Override
        public void sort(Comparable[] a) {
            int N = a.length;
            aux = new Comparable[N];
            for (int sz = 1; sz < N; sz = sz + sz){// sz子数组大小
                for (int lo = 0; lo < N - sz; lo+= sz+sz){ //均分为多个子数组,子数组进行合并为排序好的
                    merge(a, lo, lo+sz-1, Math.min(lo+sz+sz-1, N-1));
                }
            }
        }
    
        public void merge(Comparable[] a, int lo, int mid, int hi){
            //将a[lo..mid]和a[mid+1...hi]归并
            int i = lo,
                j = mid + 1;
            for(int k = lo; k <= hi; k++){//将a[lo...hi复制到aux[lo...hi]
                aux[k] = a[k];
            }
            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++];
                }
            }
        }
    }
    
    
    
    package kunpu.arithmetic;
    
    /**
     * 堆排序
     * 先让左边有序再循环下沉
     * @author zhen
     * @Date 2018/4/11 16:12
     */
    public class Pile extends Sort {
        @Override
        public void sort(Comparable[] a) {
            int N = a.length;
            for (int k = N/2; k >= 1; k--){
                sink(a, k, N);
            }
            while (N > 1){
                exch(a, 1, N--);
                sink(a, 1, N);
            }
        }
        private void sink(Comparable[] a,int k, int N){//下沉
            while (2*k <= N){
                int j = 2*k;
                if (j < N && less(j, j+1)){
                    j++;
                }
                if (!less(k, j)){
                    break;
                }
                exch(a, k, j);
                k = j;
            }
        }
    
    }
    
    
    package kunpu.arithmetic;
    
    /**
     * 快速排序
     * 規則:分而治之,数组分为两半,两半都有序的时候整个数组就有序了
     *
     * @author zhen
     * @Date 2018/4/10 9:49
     */
    public class Quick extends Sort {
        @Override
        public void sort(Comparable[] a) {
            sort(a, 0, a.length-1);
        }
    
        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);
    
        }
    
        private static int partition(Comparable[] a, int lo, int hi){
            int i = lo, j = hi + 1;
            Comparable v = a[lo]; //切分元素,中间值
            while(true){
                while(less(a[++i], v)){ //从左起找出第一个大于等于中间值的坐标i
                    if (i == hi) {
                        break;
                    }
                }
                while (less(v, a[--j])){ //从右起找出第一个小于等于中间值的坐标j
                    if (j == lo){
                        break;
                    }
                }
                if (i >= j){
                    break; //假设左边i个元素都是比中间值小的,二球右边都是比中间值大的,重合在一个点了
                }
                exch(a, i, j); //交换 比中间值小的和比中间值大的位置
            }
            exch(a, lo, j); //交换 将标准放入合适的位置
            return j; //返回该点的索引
        }
    }
    
    
    
    package kunpu.arithmetic;
    
    /**
     * 快速排序:三取样切分,中间元素往两边挑的过程
     * @author zhen
     * @Date 2018/4/10 15:39
     */
    public class Quick3Way extends Sort {
        @Override
        public void sort(Comparable[] a) {
            sort(a, 0 , a.length - 1);
        }
    
        private static void sort(Comparable[] a, int lo, int hi){
            if (hi <= lo){
                return;
            }
            int lt = lo, i = lo + 1, gt = hi;
            Comparable v = a[lo];
            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);
        }
    }
    
    
    package kunpu.arithmetic;
    
    /**
     * 选择排序
     * 规则:首先找到数组中最小的元素,其次将它和数组中第一个元素互换位置;再找剩下的最小的元素与第二个元素互换位置,周而复始
     * @author zhen
     * @Date 2018/4/2 9:38
     */
    public class Selection extends Sort{
    
        @Override
        public 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);
                }
            }
        }
    }
    
    
    package kunpu.arithmetic;
    
    /**
     * 希尔排序
     * 规则:希尔排序是针对插入排序的一种改进。使数组中任意间隔为h的元素都是有序的。类似插入排序使用不同增量
     * @author zhen
     * @Date 2018/4/2 10:39
     */
    public class Shell extends Sort {
        @Override
        public void sort(Comparable[] a) {
            int N = a.length;
            int h = 1;
            while(h < N/3){
                h = 3*h + 1;
            }
            while( h >= 1){
                //将数组变成h有序
                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);
                    }
                }
                h = h/3;
            }
        }
    }
    

      

  • 相关阅读:
    Python(1)-第一天
    读书笔记-单元测试艺术(三)-使用桩对象解除依赖
    Sql2008调试问题
    读书笔记-单元测试艺术(二)-单元测试框架
    读书笔记-单元测试艺术(一)-单元测试的基本知识
    最长回文子串
    最大连续子序列之和,最大连续子序列乘积
    计数排序与位图排序
    筛选法求素数
    传说中的华为面试题(8分钟写出代码)
  • 原文地址:https://www.cnblogs.com/aigeileshei/p/8853723.html
Copyright © 2011-2022 走看看