数据结构与算法--插入排序

排序图解

从图中可以看出,待排序的数组分为两个子数组,其中一个子数组认为是有序的,另一个数组认为是无序的。从无序的子数组取出前一个元素,在有序的子数组从后往前进行比较,找到待插入的位置

需要排序的趟次 = 数组长度 - 1


排序原理

  1. 把待排序的数组分为两组,已排序的和未排序的两个子数组
  2. 找到未排序的子数组中第一个元素,向已排序的子数组中进行插入
  3. 倒序遍历已排序的子数组,依次和待插入的元素进行比较,如果待插入的元素比已排序的前一个元素值小,则交换这两个值的位置,直到在已排序的子数组中找到一个元素小于等于待插入元素即可
  4. 重复步骤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)


算法稳定性

比较是从有序序列的末尾开始,也就是想要插入的元素和已经有序的最大者开始比起,如果比它大则直接插入在其后面,否则一直往前找直到找到它该插入的位置。如果碰见一个和插入元素相等的,那么把要插入的元素放在相等元素的后面。所以,相等元素的前后顺序没有改变,从原无序序列出去的顺序就是排好序后的顺序,所以插入排序是稳定的

算法稳定性:假设在数列中存在a[i]=a[j],若在排序之前,a[i]在a[j]前面;并且排序之后,a[i]仍然在a[j]前面。则这个排序算法是稳定的

posted @ 2022-07-25 22:30  伊文小哥  阅读(42)  评论(0编辑  收藏  举报