数据结构与算法--插入排序
排序图解
从图中可以看出,待排序的数组分为两个子数组,其中一个子数组认为是有序的,另一个数组认为是无序的。从无序的子数组取出前一个元素,在有序的子数组从后往前进行比较,找到待插入的位置
需要排序的趟次 = 数组长度 - 1
排序原理
- 把待排序的数组分为两组,已排序的和未排序的两个子数组
- 找到未排序的子数组中第一个元素,向已排序的子数组中进行插入
- 倒序遍历已排序的子数组,依次和待插入的元素进行比较,如果待插入的元素比已排序的前一个元素值小,则交换这两个值的位置,直到在已排序的子数组中找到一个元素小于等于待插入元素即可
- 重复步骤2
代码实现
public void insertionSort(int[] arr){
for (int i = 1; i < arr.length; i++) {
for (int j = i; j > 0; j--) {
if (arr[j] <= arr[j-1]){
exchange(arr,j,j-1);
}
}
}
}
public void exchange(int[] arr, int j, int i) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
时间复杂度分析
插入排序使用了双层for循环,其中内层循环的循环体是真正完成排序的代码,所以分析插入排序的时间复杂度,主要分析一下内层循环体的执行次数即可
比较的次数为:(N-1)+(N-2)+(N-3)+...+2+1=((N-1)+1)*(N-1)/2=N2/2-N/2
交换的次数为:(N-1)+(N-2)+(N-3)+...+2+1=((N-1)+1)*(N-1)/2=N2/2-N/2
总执行次数为:(N2/2-N/2)+(N2/2-N/2)=N2-N
按照大O推导法则,保留函数中的最高阶项那么最终插入排序的时间复杂度为O(N2)
算法稳定性