排序算法

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;
        }
    }
}

  

posted @ 2018-04-16 09:04  guodaxia  阅读(109)  评论(0编辑  收藏  举报