# 插入排序及其优化

## 构造排序基础类

BaseSort.java

package sort;

import edu.princeton.cs.algs4.StdOut;

public  class BaseSort {

//比较
public static boolean less(Comparable a , Comparable b) {
return a.compareTo(b)<0;
}

//交换顺序
public static void exchange(Comparable[] a , int i, int j) {
Comparable temp = a[i];
a[i] = a[j];
a[j] = temp;
}

//打印
public static void show(Comparable[] a) {
for (int i = 0; i < a.length; i++) {
StdOut.print(a[i]+" ");
}
StdOut.println();
}

//判断是否有序
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 static void insertSortByExchange(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--){
exchange(a, j-1, j);
}
}
}

## 通过“插入”实现

mark first element as sorted
for each unsorted element
'extract' the element
for i = lastSortedIndex to 0
if currentSortedElement > extractedElement
move sorted element to the right by 1
else: insert extracted element

public static void insertSortByInsert(Comparable[] a) {
int N = a.length;
for (int i = 1; i < N; i++) {
//取出元素
Comparable extract = a[i];
for (int j = i - 1; j >= 0; j--) {
if (less(extract, a[j])) {
a[j + 1] = a[j];
//插入点为开头的特殊情况
if (j == 0) {
a[0] = extract;
break;
}
} else {
a[j + 1] = extract;
break;
}
}
}
}

## 插入排序的哨兵

    public static void insertSortByGuard(Comparable[] a) {
int N = a.length;
//寻找哨兵
int min = 0 ;
for(int i=1;i<N;i++){
if(less(a[i], a[min])){
min = i;
}
}
exchange(a, 0, min);
for(int i=1;i<N;i++){
for(int j=i;less(a[j], a[j-1]);j--){
exchange(a, j-1, j);
}
}
}

## 希尔排序

public static void shellSort(Comparable[] a) {
int N = a.length;
int h=1;
while(h<N/3) h=h*3+1;
while(h>=1){
for(int i=h;i<N;i++){
for(int j=i;j>=h&&less(a[j], a[j-h]);j-=h){
exchange(a, j, j-h);
}
}
h=h/3;
}
}

## 算法效率对比

//测试算法时间
public static double sortRunTime(int N,int T,String sortName) {
double total = 0.0;
Double[] a = new Double[N];
for(int t =0 ;t<T;t++){
for(int i=0;i<N;i++)
a[i] = StdRandom.uniform();
Stopwatch timer = new Stopwatch();
if(sortName.equals("insetSortByExchange")){
insetSortByExchange(a);
}
if(sortName.equals("insertSortByGuard")){
insertSortByGuard(a);
}
if(sortName.equals("shellSort")){
shellSort(a);
}
if(sortName.equals("insertSortByInsert")){
insertSortByInsert(a);
}
total += timer.elapsedTime();
}
}
public static void main(String[] args) {
System.out.println("insetSortByExchange:\t"+sortRunTime(1000, 1000, "insetSortByExchange"));
System.out.println("insertSortByGuard:\t"+sortRunTime(1000, 1000, "insertSortByGuard"));
System.out.println("insertSortByInsert:\t"+sortRunTime(1000, 1000, "insertSortByInsert"));
System.out.println("shellSort:\t"+sortRunTime(1000, 1000, "shellSort"));

}