(一)插入排序法:以从小到大排列为例,假设数组arr中[0,i)已排好序,[i,n)还未排序。对于元素arr[i],向前比较元素大小,插入到合适的位置。
(二)循环不变量:arr[0...i)已排好序,[i...n)还未排序。把arr[i]放到合适的位置。可以通过交换元素,也可以通过平移元素。
(三)具体代码:
只是比较数组中的数字(按从小到大的顺序):
① [0...i)有序,[i...n)无序
//下面两种写法本质上都是一样的
public void InsertionSort(int[] arr){
for (int i = 0;i < arr.length;i ++)
for (int j = i;j - 1 >= 0;j --)
if (arr[j - 1] > arr[j])
swap(arr,j,j-1);
else break;
}
public void InsertionSort2(int[] arr){
for (int i = 0;i < arr.length;i ++)
for (int j = i;j - 1 >= 0 && arr[j - 1] > arr[j];j --)
swap(arr,j,j-1);
}
//交换元素
public void swap(int[] arr,int i,int j){
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
上面的方法可以实现排序的效果,但一次交换需要三次操作。如果数据量很大的情况下,也是很耗时的,所以我们放弃两两元素交换的做法,采用“先记下当前元素,然后移动元素”的方法:
public void InsertionSort3(int[] arr){
for(int i = 0;i < arr.length;i ++){
int t = arr[i];
int j;
for (j = i;j - 1 >= 0;j --)
if (arr[j - 1] > t)
arr[j] = arr[j - 1];
else break;
//为什么用break?
//t前面只要有一个元素小于t,就说明t前面所有的元素都小于t,已经排好序了,就不用再往前比较了
arr[j] = t;
}
}
//这个写法本质上和上面的相同
public void InsertionSort4(int[] arr){
for(int i = 0;i < arr.length;i ++){
int t = arr[i];
int j;
for (j = i;j - 1 >= 0 && arr[j - 1] > t;j --)
arr[j] = arr[j - 1];
arr[j] = t;
}
}
② [0...i)无序,[i...n)有序
public void InsertionSort(int[] arr){
for (int i = arr.length - 1;i > 0;i --){
int t = arr[i];
int j;
for (j = i;j + 1 < arr.length && arr[j + 1] < t ;j ++)
arr[j] = arr[j + 1];
arr[j] = t;
}
}
比较其他对象(扩展性更强):
public class InsertionSort {
private InsertionSort(){}
//更简便,不交换,只平移。
//[0...i)有序,[i...n)无序
public static <E extends Comparable<E>> void sort(E[] arr){
for( int i = 0;i< arr.length;i ++){
E t = arr[i];
int j;
for( j = i;j - 1 >= 0 && arr[j - 1].compareTo(t) > 0;j --)
arr[j] = arr[j - 1];
arr[j] = t;
}
}
//[0,i)无序,[i,n)有序
public static <E extends Comparable<E>> void sort3(E[] arr){
for(int i = arr.length - 1;i > 0;i -- ){
E t = arr[i];
int j;
for(j = i;j + 1 < arr.length;j ++)
if( arr[j+1].compareTo(t) < 0)
arr[j] = arr[j + 1];
else break;
arr[j] = t;
}
}
//最好不要这么写,一次交换三次操作,略复杂。
public static <E extends Comparable<E>> void sort2(E[] arr){
for(int i = 0; i < arr.length; i ++) {
// //写法一
// for( int j = i; j - 1 >=0 ; j-- ){
// if( arr[ j - 1 ].compareTo(arr[ j ]) > 0 )
// swap(arr,j,j-1);
// else break;
// }
//写法二
for(int j = i;j - 1 >=0 && arr[j-1].compareTo(arr[j]) > 0 ;j --)
swap(arr,j-1,j);
}
}
public static <E> void swap(E[] arr,int i,int j){
E temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
博主也正在学习中,如果有错误或疑问欢迎评论私信交流讨论!