插入排序详细分类及代码实现

本文详细介绍多种插入排序算法,包括直接插入排序、折半插入排序、2路插入排序、表插入排序及希尔排序等,并提供了每种算法的实现代码与测试示例。

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

1. 直接插入,升序
将一个记录插入到已排序好的有序表中,从而得到一个新,记录数增1的有序表。即:先将序列的第1个记录看成是一个有序的子序列,然后从第2个记录逐个进行插入,直至整个序列有序为止。
直接插入头文件

#pragma once
#define MAXSIZE 20
#define T int

typedef T Seqlist[MAXSIZE];

void swap(T *a,T *b)
{
    T temp = *a;
    *a = *b;
    *b = temp;
}

void Insert(Seqlist &L,int n)  //
{
    for(int i = 1;i<n;++i)
    {
        if(L[i] < L[i-1])// 若第i个元素大于i-1元素,直接插入。小于的话,移动有序表后插入    
            {
            swap(&L[i],&L[i-1]);
            for(int j = i-1;j>0&&L[j]<L[j-1];--j)
            {
            swap(&L[j],&L[j-1]);
            }
        }
    }
}

直接插入测试文件

#include<iostream>
#include"sort.h"
using namespace std;

void main()
{
    Seqlist L = {16,25,8,25,21,49,3,5};
    int n = 8;
    Insert(L,n);
    for(int i = 0;i < 8;++i)
    {
        cout<<L[i]<<"  ";
    }
}

2.(折半插入)二分法插入算法
比较直接插入,减少了关键值的比较,但数据移动次数不变

#define MAXSIZE 20
#define T int

typedef T Seqlist[MAXSIZE];

void Binary_insert(Seqlist &L,int n)  //
{
    for(int i = 2;i <n;++i)
    { 
        L[0] = L[i];  //具备临时空间功能
        int low = 1;
        int high = i-1;
        while(low <= high)
        {
            int mid = (low + high)/2;
            if(L[0] >= L[mid])
            {
                low = mid + 1;
            }
            else
            {
                high = mid - 1;
            }
        }
        for(int k = i;k > high+1;--k)
        {
            L[k] = L[k-1];  
        }
        L[high+1] = L[0];

    }
}

二分法插入算法的测试

void main()   
{
    Seqlist L = {0,16,25,8,25,21,3,49,5};
    int n = 9;
    //Insert(L,n);
    Binary_insert(L,9);
    for(int i = 1;i < 9;++i)  //注意:此时L[0]储存的是临时对象的值
    {
        cout<<L[i]<<"  ";
    }
}

3. 2路插入排序
需借助一个与数据相同大小的内存空间,在折半插入排序算法上,减少其数据移动次数

#define MAXSIZE 20
#define T int

typedef T Seqlist[MAXSIZE];

void Two_ways_insert(Seqlist &L,int n)   
{
    int i,j;
    Seqlist sq;//需借助一个大小与原数据相同大小的内存空间
    sq[0] = L[0];
    int head,tail;
    head = tail = 0;
    for(i = 1;i < n;++i)
    {
        if(L[i] < sq[head])
        {
            head = (head - 1 + n)%n;//循环赋值,模是关键
            sq[head] = L[i];
        }
        else if(L[i] > sq[tail])
        {
            tail++;
            sq[tail] = L[i];
        }
        else
        {
            tail++;
            sq[tail] = sq[tail-1];
            for(j = tail-1;L[i]<sq[(j-1+n)%n];j=(j-1+n)%n)
            {
                sq[j] = sq[(j-1+n)%n];
            }
            sq[j] = L[i];
        }
    }
    for(i = 0;i < n;++i)
    {
        L[i] = sq[head];
        head = (head + 1)%n;
    }
}

2路插入排序测试文件

void main()  
{
    Seqlist L = {16,25,8,25,21,3,49,5};
    int n = 8;
    //Insert(L,n);
    Two_ways_insert(L,8);
    for(int i = 0;i < 8;++i)
    {   
        cout<<L[i]<<"  ";
    }
}

4. 表插入排序
采用静态链表作为底层存储结构,达到不移动数据只改变指针来完成,求得一个有序链表节点,不能直接查找

#define MAXSIZE 20  //默认定义数据大小为20
#define T int
typedef T Seqlist[MAXSIZE];
#define MAXVALUE 0x7fffffff
typedef struct SLNode
{
    T data;
    int link;
}SLNode;

typedef SLNode Table[MAXSIZE];

void Table_insert_sort(Table &t,int n)
 {
    t[0].link = 1;
    int p,q;//q为p的前驱
    for(int i = 2;i<n;++i)
    {
        p = t[0].link;
        q = 0;
        while(p != 0 && t[p].data <= t[i].data)
        {
            q = p;
            p = t[p].link;
        }
        t[i].link = t[q].link;
        t[q].link = i;
    }
}

表插入测试

void main()       
{
    Seqlist L = {0,16,25,8,25,21,3,49,5};
    //Seqlist L = {0,49,38,65,97,76,13,27,49};
    int i,n = 9;

    Table tb;
    tb[0].data = MAXVALUE;
    tb[0].link = 0;
    for(i = 0;i<n;++i)
    {
        tb[i].data = L[i];
        tb[i].link = 0;
    }
    Table_insert_sort(tb,n);

    for(i = 0;i<n;++i)
    {
        cout<<tb[i].data<<"      ";
    }
    cout<<endl<<endl;
    for(i = 0;i<n;++i)
    {
        cout<<tb[i].link<<"       ";
    }
    cout<<endl<<endl;
    for(i = 0;i<n;++i)
    {
        cout<<i<<"       ";
    }
    cout<<endl<<endl;
}

这里写图片描述
下标
可以理解:从0下标对应位置开始,0下标存的是指针6,6下标对应值3;值3对应对应指针8,8下标对应值5;值5对应指针3,3下标对应值8,,,,

5.希尔排序(缩小增量排序)
希尔排序在前面几种插入方式的基础上,在时间效率上有所提高
先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录“基本有序”时,再对全体记录进行依次直接插入排序

#define MAXSIZE 20
#define T int

typedef T Seqlist[MAXSIZE];

void swap(T *a,T *b)
{
    T temp = *a;
    *a = *b;
    *b = temp;
}

void Shell_insert(Seqlist &L,int n,int dis)//dis为增量的值
{
    for(int i=dis+1;i<n;++i)
    {
        if(L[i]<L[i-dis])
        {
            //L[0] = L[i];
            //for()
            swap(&L[i],&L[i-dis]);          
        }

    }//L[i-dis] = L[0];
}
void Shell_sort(Seqlist &L,int n,int gap_data[],int t)  //希尔排序
{
    for(int k = 0;k<t;++k)
    {
        Shell_insert(L,n,gap_data[k]);
    }
}   

希尔排序测试文件

void main()  
{
    //Seqlist L = {0,49,38,65,97,76,13,27,49};
    Seqlist L = {0,16,24,8,25,21,3,49,5};
    int n = 9;
    //int gap_data[]={5,4,2,1};  //注意由于间距的取值,有时候希尔排序得到的并非是完全正确的排序
    int gap_data[]={4,2,1};  //3 8 5 16 21 24 25 25 49
    int t = sizeof(gap_data)/sizeof(int);
    Shell_sort(L,n,gap_data,t);
    for(int i = 1;i < 9;++i)  //注意:此时L[0]储存的是临时对象的值
    {   
        cout<<L[i]<<"  ";
    }
}
注意:希尔排序的间距的取值,一般为:gap = gap/3 + 1;
                          或:gap = n/2 ;gap = gap/2;
    对于规模较大的序列(n<1000),希尔排序具有较高的效率,且代码实现简单,所以应用较广
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值