技术交流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)
- 稳定性:稳定