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