【C语言数据结构】插入排序:直接插入排序 | 折半插入排序 | 希尔排序(原理和代码)

在这里插入图片描述

插入排序

主要操作是插入,其基本思想是:每次将一个待排序的记录按其关键码的大小插入到一个已经排好序的有序序列中,直到全部记录排好序为止。
插入排序的分类:

  • 直接插入排序
  • 折半插入排序
  • 希尔排序

一、插入排序

1、思路:

初始时把第一个数看成一个有序数列,把 r[ 0 ]=剩下的数列的第一个数,与有序数列的最后一个数比较;
如果这个数大于有序数列的最后一个数,那么这个数不动(加入了有序数列);
如果小于,那么有序数列的最后一个数向后移动一位,再与有序数列的倒数第二个数比较,知道这个数大于有序数列的数,否则被比较的有序数列数字后移。
一直重复这个动作。

2、代码

void insertsort(int r[],int n)
{
    int i,j;
    for(i=2;i<=n;i++)
    {
        r[0]=r[i];
        j=i-1;
        while(r[0]<r[j])
        {
            r[j+1]=r[j];
            j--;
        }
        r[j+1]=r[0];
    }
}

int main()
{
    int a[13]={0,12,67,56,16,25,22,48,34,43,68,1,23}; //a[0]不存数据
    insertsort(a,12);
    for(int j=1;j<=12;j++)
        printf("%d ",a[j]);
    return 0;
}

3、性能

最好 O(n)
最坏:O(n2)
时间复杂度:O(n
2)
直接插入排序算法简单、容易实现,适用于待排序记录基本有序或待排序记录较小时。

二、折半插入排序

1、思想

是直接插入排序的改进
对于第i个插入点,可以对前有序的 i-1 序列进行折半查找,减少比较次数。
步骤与直接插入排序一样

  • 暂存待插记录
  • 查找插入位置
  • 后移记录
  • 插入待插记录

2、代码

void BinaryInsertsort(int r[],int n)
{
    int i,j,mid,low,high;
    for(i=2;i<=n;i++)
    {
        r[0]=r[i];
        low=1;  high=i-1;
        while(low<=high)
        {
            mid=(low+high)/2;
            if(r[mid]>r[0])
                high=mid-1;
            else
                low=mid+1;
        }

        for(j=i-1;j>=high+1;j--)
            r[j+1]=r[j];
        r[high+1]=r[0];
    }
}

3、性能

减少了关键字的比较次数,但记录的移动次数并未减少
时间复杂度为 O(n*2)

三、希尔排序

直接插入排序的改进:

  • 若待排序记录按关键码基本有序时,直接插入排序的效率可以大大提高;
  • 由于直接插入排序算法简单,则在待排序记录数量n较小时效率也很高。

1、思想(分治思想)

将整个待排序记录分割成若干个子序列,在子序列内分别进行直接插入排序,
待整个序列中的记录基本有序时,对全体记录进行直接插入排序。

  • 分割的组数:数据数 / 2 , 注意组内元素是分隔的。
  • 直接插入排序每次移动一位,希尔排序每次移动 d 位
    在这里插入图片描述

2.代码

void Shellsort(int r[],int n)  //希尔排序,r[0]不存数据
{
    int d,i,j;
    for(d=n/2;d>=1;d=d/2)
    {
        for(i=d+1;i<=n;i++)
        {
            r[0]=r[i];
            j=i-d;
            while(j>0 && r[0]<r[j])
            {
                r[j+d]=r[j];
                j=j-d;
            }
            r[j+d]=r[0];

        }
    }
}

3.性能

时间复杂度:O(n*2) ~ O(nlogn)之间

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yyzuimei

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值