排序系列【比较排序系列之】直接插入排序
最近在和小伙伴们一起研究排序,排序分好多总,后期会做整体总结,本篇则主要对插入排序进行一个整理。
插入排序(insert sorting)的算法思想十分简单,就是对待排序的记录逐个进行处理,每个新纪录与同组那些已排好序的记录进行比较,然后插入到适当的位置。用三个字总结就是—-“多对一”的关系。
插入排序分好几种,比如二分插入排序,交换插入排序,直接插入排序,本篇我们重点总结最熟悉的“直接插入排序”。
比如有一个数组【45 34 78 12 34’ 32 29 64】,我们针对此进行一下讲解。
排序过程 数组{45 34 78 12 34’ 32 29 64} |
---|
第一遍 45和34比较,34<45,所以排序完成为34 45 78 12 34’ 32 29 64 |
第二遍 78和34 45比较 78>45 78>34,所以位置不变,排序完为 34 45 78 12 34’ 32 29 64 |
第三遍 12和34 45 78比较 12<78 左移+1,12<45 左移+2,12<34 左移+3,排序完为 12 34 45 78 34’ 32 29 64 |
第四遍 34’ 左移+2 排序完 12 34 34’ 45 78 32 29 64 |
第五遍 32 左移+4 排序完 12 32 34 34’ 45 78 29 64 |
第六遍 29 左移+6 排序完 12 29 32 34 34’ 45 78 64 |
第七遍 64 左移+1 排序完 12 29 32 34 34’ 45 64 78 |
用代码实现的话其实更简单,引入一个临时变量,具体看代码:
public static void main(String[] args) {
Test2 test2 = new Test2();
//定义一个数组
int[] array = {45, 34, 78, 12, 34, 32 ,29 ,64};
test2.insertSort(array);
System.out.println(Arrays.toString(array));
}
void insertSort(int[] array) {
//定义的临时变量
int tempRecord;
//i从1开始的原因是j=j-1
for (int i = 1; i < array.length; i++) {
tempRecord = array[i];
int j = i - 1;
//j不能为负数,根据索引判定值大小,通过临时变量进行交换
while (j >= 0 && tempRecord < array[j]) {
array[j + 1] = array[j];
j = j - 1;
}
array[j + 1] = tempRecord;
}
}
2018年07月30日14:30:55补充:
array[j + 1] = tempRecord,应该放入while循环内,因为若tempRecore不小于array[j],则此次i循环则直接结束。
通过代码我们来看一下时间复杂度和空间复杂度。
因为我们只引入了一个辅助存放插入记录的临时变量,因此空间代价为一个记录大小 及O(1);
当数据正序时,如上我们口述的排序比较过程,执行效率最好,每次插入都不用移动前面的元素,有N个元素参与比较,时间复杂度为O(N)。
当数据反序时,则执行效率最差,每次插入都要前面的元素后移,
i=1时,移动2-1;
i=2时,移动3-1;
当i=n时,移动n-1;
求和公式:n(n-1)/2=O(n2)
所以最坏的时间复杂度为O(N2)