直接插入排序和希尔排序

来源:互联网 发布:js点击按钮关闭div 编辑:程序博客网 时间:2024/04/30 05:24

一:插入排序
在一组无序的数组中,假设第一个有序,每一次数组中剩余的元素与第一个比较,然后逐个插入到一个有序的序列中,直到这个数组所有的数字有序为止;
二:直接插入算法
这里写图片描述
算法思路:
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
原创粉丝点击