目录
1.直接插入排序:
2.算法优化分析:
3.时间复杂度分析:
4.空间复杂度分析:
插入排序:就是将一个元素插入到一个排好序的有序数组中。具体怎么理解呢?
对于一个包含N个数组的元素,他会从 [0,1] 区间开始插入排序,即将 1 插入到数组 {2} 的合适位置;接着从 [0,2] 区间开始排序,即将 4 插入到数组 {1,2}的合适位置。依次类推,总共执行N-1轮。
注意:将待排序元素插入到数组的合适位置时,其后的数组元素需要一次后移一位。
原始数组 2 1 4 3 5
一轮排序 1 2 4 3 5
二轮排序 1 2 4 3 5
三轮排序 1 2 3 4 5
四轮排序 1 2 3 4 5
public class InsertSort {
public static void insertSort(int[] arr) {
//正常情况下,插入排序需要N-1轮的循环遍历
for(int i=0 ; i arr[i+1]) {
int temp = arr[i+1]; //将待排序元素存入临时变量
int k = i+1; //将待排序元素的索引赋值给变量k
//在括号中为true时,while才会执行循环
while(k>0 && arr[k-1]>temp) {
arr[k] = arr[k-1]; //将数组中满足条件的元素后移一位
k--; //维护变量,即继续对有序数组前面的元素进行遍历
}
arr[k] = temp; //将临时变量中的待排序元素放到数组的合适位置
}
}
}
}
插入排序需要不断将一个元素插入到有序数组的合适位置,正常情况下需要从一端逐个比较,直到满足条件为止。最坏的情况下需要与有序数组中的每个元素都比较一下,因此在查找有序数组合适位置时可以使用二分查找算法进行优化。
public class InsertSort_Opt {
/**
* 在[left,right]的数组区间中寻找元素high的合适位置,以升序为例
* @param arr
* @param start
* @param end
* @param high
* @return 返回一个插入位置的索引值
*/
public static int binarySelect(int[] arr,int start,int end,int high) {
//定义二分查找的区间位置变量,以及中间位置变量
int left = start;
int right = end;
//设定递归算法的结束标志:数组最后一轮区间容量为1.left=right
if(left >= right) {
return (high>=arr[left]) ? left+1:left;
}else {
//给定二分查找的中间位置
int middleIndex = (left+right)/2;
if(high == arr[middleIndex]) {
return middleIndex;
}else if(high > arr[middleIndex]) {
left = middleIndex+1;
return binarySelect(arr,left,right,high); //递归调用二分查找算法
}else {
right = middleIndex-1;
return binarySelect(arr,left,right,high);
}
}
}
public static void insertSort(int[] arr) {
for(int i=0 ; i arr[i+1]) {
int temp = arr[i+1];
int k = i+1; //无序位置的索引
int index = binarySelect(arr,0,i,arr[i+1]); //待排序元素的插入位置
while(k-1 >= index) { //k-1为有序位置的索引
arr[k] = arr[k-1]; //将插入位置及其后面的数组元素依次后移一位
k--;
}
arr[index] = temp;
}
}
}
}
3.1优化前:
对于元素个数为N的数组:
1.第一轮从第二个元素开始,与前面的有序数组元素依次比较,需要比较 1 次,之后插入到数组的合适位置,其后元素依次后移一位,同时维护待排序元素的索引值(+1);
2.第二轮从第三个元素开始,与前面的有序数组元素依次比较,需要比较 2 次,之后插入到数组的合适位置,其后元素依次后移一位,同时维护待排序元素的索引值(+1);
......
3.第N-1轮从第N个元素开始,与前面的有序数组元素依次比较,需要比较 N-1 次,之后插入到数组的合适位置,其后元素依次后移一位,同时维护待排序元素的索引值(+1);
根据等差数列的求和公式:Sn = (a1+an)*(N-1)/2。得到插入排序最坏的时间复杂度为O(N^2)。
3.2优化后:
对于N个元素的数组而言,逐个对比数组元素寻找合适位置的时间复杂度最坏为O(N),而使用二分查找算法寻找合适位置的时间复杂度最坏为O(log(N))。因此,时间复杂度较优化前有很大的性能提升。
算法优化前后,都需要个位数以内的临时变量,因此空间复杂度为O(1)。