直接插入排序和希尔排序

一:插入排序
在一组无序的数组中,假设第一个有序,每一次数组中剩余的元素与第一个比较,然后逐个插入到一个有序的序列中,直到这个数组所有的数字有序为止;
二:直接插入算法
这里写图片描述
算法思路:
1:我们先假设第一个有序的数字下标为end,
2:下一个要插入的数字(tmp)继续构成有序就直接插入,此时end向后挪一位,
3:继续插入元素,如果下一个插入的数字和第一个不成构成有序,先与前一个元素交换,然后把end的下标–,直到所有的元素都有序结束。
实现

template<class T>
struct Less
{
    bool operator() (const T &a, const T &b)
    {
        return a < b;
    }
};

template<class T>
struct Greater
{
    bool operator() (const T &a, const T &b)
    {
        return a >b;
    }
};

template<class T,class Compare>
void InsertSort(T * _a, size_t n)
{
    for (size_t i = 0; i< n - 1; i++)
    {
        int end = i;
        int tmp = _a[end + 1];
        while (end >= 0)
        {
            if (Compare()(_a[end],tmp))
            {
                _a[end + 1] = _a[end];
            }
            else
            {
                break;
            }
            end -= 1;
        }
        _a[end + 1] = tmp;
    }
}
template<class T>
void PrintSort(T*a, size_t  n)
{
    for (size_t i = 0; i < n; ++i)
    {
        cout << a[i] << " ";
    }
    cout << endl;
}
void TestSelect()
{
    int a[] = { 1, 5, 2, 4, 3, 7, 9, 8, 0, 6 };
    int n = sizeof (a) / sizeof(a[0]);
    InsertSort<int, Greater<int>>(a, n);
    PrintSort(a, n);
}

分析:
直接插入排序最坏的时间复杂度O(N^2),也就是将一个有序的数组逆序,最好的时间复杂度O(N),就是有序;那么如何让插入算法更加高效呢?
三:希尔排序
希尔排序又称缩小增量排序,我们可以看成是直接插入排序的改进版本;
,当数字的基数很大时,而且都接近无序,如果用插入算法一个个比较后再插入,时间很高,我们可以借助分制的思想,我一个大的无序数组,分成若干个小序列列,再进行插入排序这样就会很快;

这里写图片描述
算法思路:
1:首先进行预排序,将大的元素尽快到后面,小的元素尽快到前面
2:然后取间距gap

template<class T>
struct Less
{
    bool operator() (const T &a, const T &b)
    {
        return a < b;
    }
};

template<class T>
struct Greater
{
    bool operator() (const T &a, const T &b)
    {
        return a >b;
    }
};
template<class T>
void PrintSort(T*a, size_t  n)
{
    for (size_t i = 0; i < n; ++i)
    {
        cout << a[i] << " ";
    }
    cout << endl;
}
template<class T,class Compare>
void ShellSort(T*_a, size_t n)
{
    int gap =n;
    while (gap > 1)
    {
        gap =gap / 3 +1;
        for (size_t i = 0; i < n-gap; ++i)
        {
            int end = i;
            int tmp = _a[end + gap];
            while (end >= 0)
            {
                if (Compare()(_a[end], tmp))
                {
                    _a[end+gap] = _a[end];
                }
                else
                {
                    break;
                }
                end -= gap;
            }
            _a[end + gap] = tmp;
        }
    }
}

void TestShellSort()
{
    int a[] = { 1, 5, 2, 4, 3, 7, 9, 8, 0, 6 };
    int n = sizeof(a) / sizeof(a[0]);
    ShellSort<int, Less<int>>(a, n);
    PrintSort(a, n);
}

四:总结:
1:直接插入排序:
适合一个有序的序列。而且范围不是很大,快速高效,时间复杂度最快O(n)
缺陷:
当序列的范围很大时,或者逆序时时间复杂度O(n^2)
2:希尔排序:
解决序列的范围很大时的排序;
分制思想:将大的序列,根据距离分成若干个小的序列;
每个小的序列进行插入排序,当距离为1时,进行直接插入排序。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值