排序——插入排序

本文详细介绍了三种插入排序算法:直接插入排序、折半插入排序和希尔排序。通过具体实例展示了每种排序方法的过程,并提供了相应的C++实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

插入排序

这里总结一下三种插入排序的算法:

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

直接插入排序

直接插入排序是一种最简单的排序方法,它的基本操作就是将一个记录插入到已排好序的有序表中,从而得到一个新的、记录数增1的有序表。

为了在查找插入位置的过程中避免数组下标出界,在r[0]处设置监视哨。

举例:

有一序列为:
i=1: (5) 4 6 8 7 2 3
i=2: (4 5) 6 8 7 2 3
i=3: (4 5 6) 8 7 2 3
i=4: (4 5 6 8) 7 2 3
i=5: (4 5 6 7 8) 2 3
i=6: (2 4 5 6 7 8) 3
i=7: (2 3 4 5 6 7 8)

实现代码如下:

/*
    InsertSort Implementation
    Author:zzj
    Date:17-6-17
*/
#include<cstdio>
using namespace std;
const int maxn = 100;
int a[maxn];
int n;
void InsertSort(int *a)
{
    int i,j;
    for(i=2; i<=n; i++)
    {
        if(a[i] < a[i-1])     //需要将a[i]插入有序子表中 
        {
            a[0] = a[i];      //复制为哨兵 
            a[i] = a[i-1];
            for(j=i-2; a[0] < a[j]; j--)
                a[j+1] = a[j];//记录后移 
            a[j+1] = a[0];    //插入到正确位置 
        }
    }
} 
int main()
{
    scanf("%d", &n);
    int i,j;
    for(i=1; i<=n; i++){
        scanf("%d", &a[i]);
    }   
    InsertSort(a);
    for(int i=1; i<=n; i++)
    {
        printf("%d ", a[i]);
    }
    return 0;
}

折半插入排序

这里再提供一种减小了比较次数的插入排序算法——折半插入排序,正是利用了插入到有序子表这一特点,有序就可以用二分。
就是找到要插入的位置是通过二分法来查找,这样会减少次数。

/*
    BInsertSort Implementation
    Author:zzj
    Date:17-6-17
*/
#include<cstdio>
using namespace std;
const int maxn = 100;
int a[maxn];
int n; 

void BInsertSort(int *a)
{
    int low, high, m;
    for(int i=2; i<=n; i++)
    {
        a[0] = a[i];         //将a[i]暂存到a[0] 
        low = 1, high = i-1;     
        while(low <= high)   //在a[low..high]中折半查找有序插入的位置 
        {
            m = (low + high)/2;
            if(a[0] < a[m]) high = m-1;
            else low = m+1;
        }
        for(int j=i-1; j>=high+1; j--) a[j+1] = a[j];//记录后移 
        a[high+1] = a[0];                            //插入 
    }
}
int main()
{
    scanf("%d", &n);
    int i,j;
    for(i=1; i<=n; i++){
        scanf("%d", &a[i]);
    }   
    BInsertSort(a);
    for(int i=1; i<=n; i++)
    {
        printf("%d ", a[i]);
    }
    return 0;
}

希尔排序

最后再介绍一下这个排序方法。
基本思想是:先将整个待排记录序列分割成若干子序列分别进行直接插入排序,待整个序列中的记录“基本有序”时,再对全体记录进行一次直接插入排序。

举例:

有一序列为:
初始态: 5 4 6 8 7 2 3  增量先是5
第一趟: 2 3 6 8 7 5 4  增量变为3 
第二趟: 2 3 5 4 7 6 8  增量变为1
第三趟: 2 3 4 5 6 7 8  
/*
    ShellSort Implementation
    Author:zzj
    Date:17-6-17
*/
#include<cstdio>
using namespace std;
const int maxn = 100;
int a[maxn];
int n; 
/*
    希尔插入排序与直接插入相比,修改了:
    1.前后记录位置的增量为dk,而不是1
    2.a[0]只是暂存单元,不是哨兵 
*/
void ShellInsert(int *a, int dk)
{
    int i,j;
    for(i=dk+1; i<=n; i++)
    {
        if(a[i] < a[i-dk])  //需将a[i]插入到有序增量子表 
        {
            a[0] = a[i];    //暂存在a[0] 
            for(j=i-dk; j>0 && a[0] < a[j]; j-=dk)
                a[j+dk] = a[j];//记录后移,查找插入位置 
            a[j+dk] = a[0];    //插入 
        }
    }
}
/*希尔排序*/
void ShellSort(int *a, int *dlta, int t)
{
    for(int i=0; i<t; i++)
    {
        ShellInsert(a, dlta[i]);//增量逐渐递减为1
    }
}
int main()
{
    scanf("%d", &n);
    int i,j;
    for(i=1; i<=n; i++){
        scanf("%d", &a[i]);
    }   
    int dt[3] = {5, 3, 1};
    ShellSort(a, dt, 3);
    for(int i=1; i<=n; i++)
    {
        printf("%d ", a[i]);
    }
    return 0;
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值