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

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


1. 基本思想

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

2. 排序流程

这里写图片描述

3. 算法实现

代码

#include <stdio.h>

#define N 9
int 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: 0
Sorting...
No.1    8 9 7 6 5 4 3 2 1   nnFor: 1  Move: 1  nCompare: 1
No.2    7 8 9 6 5 4 3 2 1   nnFor: 2  Move: 3  nCompare: 3
No.3    6 7 8 9 5 4 3 2 1   nnFor: 3  Move: 6  nCompare: 6
No.4    5 6 7 8 9 4 3 2 1   nnFor: 4  Move:10  nCompare:10
No.5    4 5 6 7 8 9 3 2 1   nnFor: 5  Move:15  nCompare:15
No.6    3 4 5 6 7 8 9 2 1   nnFor: 6  Move:21  nCompare:21
No.7    2 3 4 5 6 7 8 9 1   nnFor: 7  Move:28  nCompare:28
No.8    1 2 3 4 5 6 7 8 9   nnFor: 8  Move:36  nCompare:36
Sorted.

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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值