技术交流QQ群:1027579432,欢迎你的加入!

一.原理

  • 由于是直接插入排序,下面假设原始数组中已经有一个元素是5,待插入的元素是3,所以下面的程序中待插入元素的下标i从2开始。数组下标0的位置作为哨兵,暂存待插入的元素。直接插入算法的主要步骤分3步:首先待插入元素的下标i从2开始移动,循环到数组最大长度对应的索引处L->len;然后,将待插入的元素与前一个元素即下标是i-1的元素进行比较。如果前一个元素比待插入的元素大,此时执行直接插入算法。否则不执行,i继续向后移动一个位置,重新插入一个新的元素。接着,将待插入元素暂存在哨兵L->r[0]处(如下图的①)。再接着,将数组的元素向右移动一个位置(即增量为1,给待插入的元素留个位置,准备插入元素啦,如下图的②)。最后,将暂存在哨兵L->r[0]处的带插入元素放到由于上一步向右移动获得的空白位置处,完成整个插入操作(如下图的③),整个过程中的增量increment始终等于1。

二.插入过程

直接插入排序.jpg

三.完整代码如下:

```
    #include "iostream"

    using namespace std;

    #define OK 1
    #define ERROR 0
    #define TRUE 1
    #define FALSE 0
    #define MAXSIZE 10
    #define N 9

    typedef int Status;
    typedef struct
    {
        int r[MAXSIZE+1];
        int len;
    } Sqlist;

    void show(Sqlist L)
    {
        for (int i = 1; i <= L.len; i++)
            cout << L.r[i] << " ";
        cout << endl;
    }

    // 直接插入排序
    void InsertSort(Sqlist *L)
    {
        int i, j;
        for (i = 2; i <= L->len; i++)
        { // 插入的元素从下标为2开始
            if (L->r[i] < L->r[i - 1])
            {                      // 插入的元素比之前的元素值小,就进行交换操作
                L->r[0] = L->r[i]; // 下标为0的位置存放的是哨兵
                for (j = i - 1; L->r[j] > L->r[0]; j--)
                    L->r[j + 1] = L->r[j]; // 进行移动操作
                L->r[j + 1] = L->r[0];  // 插入新的元素到正确的位置
            }
        }
    }



    int main(){
        Sqlist L0;
        int d[N] = {9, 1, 5, 8, 3, 7, 4, 6, 2};
        for(int i = 0; i < N; i++)
            L0.r[i+1] = d[i];
        L0.len = N;
        cout << "直接插入排序前: ";
        show(L0);
        cout << "直接插入排序后: ";
        InsertSort(&L0);
        show(L0);
        return 0;
    }
```
  • STL实现
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;


void InsertSort(vector<int>& v){
    int n = v.size();
    for(int i=1; i < n; ++i){  // 假设第一个元素v[0]以已排好序,从第二个元素开始插入
        int temp = v[i];
        for(int j = i-1; j>=0; --j){
            if(temp < v[j]){
                v[j+1] = v[j];
                v[j] = temp;
            }
            else{
                break;
            }
        }
    }
}

// 打印元素
void PrintV(vector<int>& v){
    for(auto &e: v){
        cout << e << ' ';
    }
    cout << endl;
}

int main(){
    vector<int> v{7, 30, 16, 4, 1, 2, 9};
    cout << "直接插入排序前: ";
    PrintV(v);
    InsertSort(v);
    cout << "直接插入排序后: ";
    PrintV(v);
    return 0;
}

四、直接插入排序时间复杂度总结:

  • 平均时间复杂度:O(n**2)
  • 最好情况:O(n)
  • 最坏情况:O(n**2)
  • 空间复杂度:O(1)
  • 稳定性:稳定