十大排序算法之 插入排序

104 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第15天,点击查看活动详情

插入排序原理:
算法的着力点在于有序序列,开始定位一个对象,作为最小的已排序的序列。和我们打扑克的思路是一样的,未抓取的是未排序序列,手里的牌是已排序序列,未排序抓取一张和手里的牌对比,并插入正确位置,直到抓完牌,排序也就完成了。

可以看出直接插入模式虽不需要额外空间,但比较的过程中会有较多的交换操作,已排好序的序列可能会不断的往后挪位。
这中间不会出现对象相对位置的变化,所以他是稳定的算法。它的最好时间复杂度是O(n),一般和最差时间复杂度O(n2)。

一般流程:

  1. 选择第一个对象为已排好的序列;
  2. 第二个对象和第一个对象比较,大于或者等于不挪位,小于则两者交换位置,第一二位置排序完成;
  3. 如上思路,如果排序已完成n-1个对象,第n个位置依次往前位置比较。小于的情况下交换位置,直到找到大于等于的情况为止;
  4. 直到完成全部对象的选取,则完成无序序列的排序。

代码实例:

#include<stdio.h>
#include <stdlib.h>
#include<unistd.h>
#include <string.h>
#include <errno.h>

#define SWAP(a1, a2, type) do {type temp = a1; a1 = a2; a2 = temp;} while(0)

int Cnt = 0;
int NumArr[200] = {0};

void PrintNums()
{
    for(int i = 0;i < Cnt;i++){
        fprintf(stdout," %d-",NumArr[i]);
    }
}

int main(int argc, char** argv)
{
    if(argc == 1) {
        fprintf(stderr,"%s:need a some arg\n",argv[0]);
        exit(1);
    }
    int CntTemp = Cnt = argc -1;

    for(int i = 0;i < Cnt;i++){
        NumArr[i] = atoi(argv[i+1]);
    }
   
    fprintf(stdout,"【Insertion Sort】inputNum:");
    PrintNums();
    fprintf(stdout,"\n");

    for(int a = 1;a < Cnt;a++){
        for(int b = a;0 < b;b--){
            if(NumArr[b] < NumArr[b-1]) SWAP(NumArr[b],NumArr[b-1],int);
        }
    }

    fprintf(stdout,"result:");
    PrintNums();
    fprintf(stdout,"\n");
    return 0;

}

测试结果,如下 image.png

优化方式: 在比较位置插入数值的过程中,因为是与有序序列比较,所以可以用二分法减少比较次数,比较次数可以较少一半,优化时间复杂度。