插入排序及其优化

Posted 恪愚

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了插入排序及其优化相关的知识,希望对你有一定的参考价值。

直接插入排序

插入排序时间复杂度最好是 O(n),最坏是O(n^2)
目前常用的 sort()方法在要排序的元素个数小于等于 10 的时候,采用插入排序实现。

1

大体思路:

  1. 将数组的第一个元素代表为已排序序列。
  2. 用下一个元素往已排序序列进行插入,插入到相应位置
  3. 循环之前的步骤,直到将所有的元素都插入到已排序序列中
#include <stdio.h>
void insertSort(int *a);
int main() {
    int a[6] = { 5,2,4,1,6,3 };   //这里也可以改成自定义数组
    insertSort(a);
    int k;
    for (k = 0; k < 6;k++) {
        printf("%d ", a[k]);
    }
    getchar();
    return 0;
}
void insertSort(int *a) {
    int i, j,key;
    //这里是从第二个元素开始的
    for (j = 1; j < 6; j++) {
        key = a[j];
        //上一个元素
        i = j - 1;

        //数组下标0开始所以>=0
        while (i >= 0 && a[i] > key){   //一定要有 i>=0 这步,这关系到 i=i-1 的下一步是否进行while循环
            a[i + 1] = a[i];
            i = i - 1;
        }
       a[i + 1] = key;
    }
}

上面代码中为什么要有"key=a[i]":选取"变量副本"。在插入排序中,当我们将每一个新元素插入到有序区间的时候,其实并不需要老老实实进行元素的两两交换!

什么意思呢?让我们拿上面例子的第3轮操作来看:
2

在这一轮中,我们需要让元素 1 逐个与有序区的元素进行比较和交换,最终交换到有序区的第一个位置。
但是按照我们的思路,这里并不需要真的进行完整交换,只需把元素 1 暂存起来,再把有序区的元素从前向后逐一复制:

  1. 暂存比较元素
    3

  2. 和前一个元素比较,发现1 < 5,复制元素 5 到下一个位置:
    4

  3. 和前一个元素比较,发现1 < 4,复制元素 4 到下一位:
    5

  4. 和前一个元素比较,发现 1 < 2,复制元素 2 到下一位:
    6

  5. 也是最后一步,把暂存的元素 1 赋值到数组的首位:
    7

显然,这样的优化方法减少了许多无谓的交换!

但是还不够好!


算法改进:

二分插入排序

与直接插排的区别:在有序区查找新元素插入位置时,为了减少元素比较次数,提高效率,采用二分查找法确定插入位置。

算法分析:
设数组为a[0…n]

  1. 将原序列分成有序区和无序区。a[0…i-1]为有序区,a[i…n] 为无序区。(i 从1开始)
  2. 从无序区中取出第一个元素,即a[i],使用二分查找算法在有序区中查找要插入的位置索引 j 。
  3. a[j]a[i-1]的元素后移,并将a[i]赋值给a[j]
  4. 重复步骤2~3,直到无序区元素为0。
// 二分插入排序
void BinInsertSort(vector<int> &vi){
    for(int i=1;i<vi.size();i++){
        int left=0;
        int right=i-1;
        int temp=vi[i]
        while(left<=right){
            int mid=(left+right)/2; //二分区域
            if(vi[mid]>temp){
                right=mid-1;       //向左缩小区域
            }
            else{
                left=mid+1;        //向右缩小区域
            }
        }
        for(int j=i-1;j>left;j--){  //vi[left,i-1]的元素整体后移 -> vi[left+1,i]
            vi[j+1]=vi[j];
        }
        vi[left]=temp;
    }
}

以上是关于插入排序及其优化的主要内容,如果未能解决你的问题,请参考以下文章

插入排序及其优化

[ 数据结构 -- 手撕排序算法第五篇 ] 快速排序 <包含hoare法,挖坑法,前后指针法> 及其算法优化

插入排序的具体实现及其原理

八大排序算法及其比较

细说冒泡排序及其五种优化算法

java代码[No.4]—快速排序算法的三种方式及其优化