插入排序—直接插入排序(Straight Insertion Sort)

来源:互联网 发布:网络直播平台怎么赚钱 编辑:程序博客网 时间:2024/06/11 17:41

插入排序—直接插入排序(Straight Insertion Sort)


    • 插入排序直接插入排序Straight Insertion Sort
      • 基本思想
      • 排序流程
      • 算法实现
      • 算法分析

1. 基本思想

将一个记录插入到已排序好的有序表中,从而得到一个新,记录数增1的有序表。即:先将序列的第1个记录看成是一个有序的子序列,然后从第2个记录逐个进行插入,直至整个序列有序为止。
要点:设立哨兵,作为临时存储和判断数组边界之用。

2. 排序流程

这里写图片描述

3. 算法实现

代码

#include <stdio.h>#define N 9int arr[N]={9,8,7,6,5,4,3,2,1};//int arr[N]={1,2,3,4,5,6,7,8,9};//int arr[N]={4,1,5,7,9,3,2,8,6};int step=0;int nMove=0; /* 移动次数 */int nFor=0; /* 循环次数 */int nCompare=0; /* 比較次数 */void print(){    int i;    printf("No.%d\t",step);    for(i=0;i<N;i++)        printf("%d ",arr[i]);    printf("\tnnFor:%2d  Move:%2d  nCompare:%2d\n",nFor,nMove,nCompare);}void sort(){    int tmp,i,j;    for(i=1;i<N;i++)    {        step++;        nFor++;        if(arr[i]<arr[i-1]) /* 如果第i个元素大于i-1元素,直接插入。否则,需要移动有序序列后插入 */        {            tmp=arr[i]; /* 复制为哨兵,存储待排序元素 */            arr[i]=arr[i-1]; /* 第一次比较后确定需要后移 */            nMove++;            j=i-1;            while(j>0 && tmp<arr[j-1])  /* 已经比较了第i-1个元素,循环从第i-2个开始比较,最差条件逆序比较到有序第一个arr[0] */            {                nCompare++;                arr[j]=arr[j-1]; /* 元素后移 */                nMove++;                j--;            }            arr[j]=tmp; /* 在位置j插入第i个元素 */        }        nCompare++;        print();    }}void main(){    printf("Before...\n");    print();    printf("Sorting...\n");    sort();    printf("Sorted.\n");}

结果

Before...No.0    9 8 7 6 5 4 3 2 1   nnFor: 0  Move: 0  nCompare: 0Sorting...No.1    8 9 7 6 5 4 3 2 1   nnFor: 1  Move: 1  nCompare: 1No.2    7 8 9 6 5 4 3 2 1   nnFor: 2  Move: 3  nCompare: 3No.3    6 7 8 9 5 4 3 2 1   nnFor: 3  Move: 6  nCompare: 6No.4    5 6 7 8 9 4 3 2 1   nnFor: 4  Move:10  nCompare:10No.5    4 5 6 7 8 9 3 2 1   nnFor: 5  Move:15  nCompare:15No.6    3 4 5 6 7 8 9 2 1   nnFor: 6  Move:21  nCompare:21No.7    2 3 4 5 6 7 8 9 1   nnFor: 7  Move:28  nCompare:28No.8    1 2 3 4 5 6 7 8 9   nnFor: 8  Move:36  nCompare:36Sorted.

4. 算法分析

  1. 当初始序列为正序时,只需外循环n-1次,每次进行一次比较且无需移动(交换)元素。此时比较次数(Cmin)和移动次数(Mmin)达到最小值。
    Cmin=n1
    Mmin=0
    此时时间复杂度为O(n)

  2. 当初始序列为反序时,需要外循环n-1次,每次排序中待插入的元素都要和[0,i-1]中的i个元素进行比较且要将这i个元素后移(arr[j] = arr[j-1]),i个元素后移总共i次,再加上tmp = arr[i]与arr[j] = tmp的两次移动,每趟移动的次数为i+2,此时比较次数(Cmin)和移动次数(Mmin)达到最大值。
    Cmax=1+2+...+(n1)=n(n1)/2=O(n2)
    Mmax=(1+2)+(2+2)+...+(n1+2)=(n1)(n+4)/2=O(n2)
    此时时间复杂度为O(n)

  3. 在直接插入排序中只使用了i、j、tmp这3个辅助元素,与问题规模无关,所以空间复杂度为O(1)。

  4. 相同元素的相对位置不变,如果碰见一个和插入元素相等的元素,那么插入元素把插入的元素放在相等元素的后面。所以相等元素的前后顺序没有改变。
    所以直接插入排序是一种稳定排序

0 0