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