此博客用于个人学习,来源于算法的书籍和网上的资料,对知识点进行一个整理。
1. 概述:
我们打牌的时候,拿到的牌经常是需要进行排序操作的,一般是一张一张的来,将每一张牌插入到其他有序的牌中的适当位置。基于这种思想,就有了插入算法——通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。
2. 算法:
将第一待排序序列第一个元素看做一个有序序列,把第二个元素到最后一个元素当成是未排序序列。从头到尾依次扫描未排序序列,将扫描到的每个元素插入有序序列的适当位置。(如果待插入的元素与有序序列中的某个元素相等,则将待插入元素插入到相等元素的后面。)
sort 方法的逻辑是——在 i 向后遍历的时候,构建一个循环向前遍历,将 a[i] (初始状态 j = i)以及前面的所有元素相邻两位元素两两进行比较,如果大小不符合规则,相邻元素之间调换位置。
3. 代码实现:
/**
* 插入排序
*/
public class Insertion {
public static void sort(Comparable[] a){
for (int i = 0;i < a.length;i++){
//将a[j]插入到a[j-1 ... 0]中
for (int j = i;j > 0 && less(a[j],a[j-1]);j--){
exchange(a,j,j-1);
}
}
}
private static boolean less(Comparable v,Comparable w){
return v.compareTo(w) < 0;
}
private static void exchange(Comparable[] a,int i,int j){
Comparable t = a[i];
a[i] = a[j];
a[j] = t;
}
private static void show(Comparable[] a){
//在单行中打印数组
for (int i = 0;i < a.length;i++){
System.out.println(a[i]+" ");
}
System.out.println();
}
/**
* 测试数组元素是否有序
* @param a
* @return
*/
public static boolean isSorted(Comparable[] a){
for (int i = 1;i < a.length;i++){
if (less(a[i],a[i-1])){
return false;
}
}
return true;
}
}
4. 特点:
所需的时间取决于输入中元素的初始顺序。例如,对一个很大且其中的元素已经有序(或接近有序)的数组进行排序会比对随机顺序的数组或者是逆序数组进行排序要快得多。
5. 算法分析:
-
时间复杂度:如果是最差的情况,即数组为逆序排列,对于 n 个元素,首先外层 for 循环要循环 n-1 次,内层 for 循环的循环次数是根据 i 来决定的,i = 1时,循环 1 次,i = 2,循环 2 次,…,i = n-1,循环 n-1 次,综合两层循环,保留高阶项,并去掉系数,那么时间复杂度为O(n^2)。
-
空间复杂度:只是用了2个循环变量以及1到2个标志和交换等的中间变量,这个与待排序的记录个数无关,空间复杂度为 O(1)。
-
稳定性:在比较的时候,如果两个数相等的话,不会进行移动,前后两个数的次序不会发生改变。例如 3885 ,当后面的8与前面进行比较的时候,由于并不小于8,所以依然保持不动。