排序算法测试-希尔排序

1、测试代码

#include <iostream>

using namespace std;
int g_loop = 0;    /* 循环计数 */
int g_move = 0;    /* 数据移动次数 */

void output_info(int *buff,int len, int flag)
{
    int i;

    if(0 == flag)
    {
        cout << "before: ";
    }
    else
    {
        cout << "after:  ";
    }

    for(i = 0; i < len; ++i)
    {
        cout << *(buff + i) << " ";
    }

    cout << endl;
}

/* 插入排序 */
void insert_sort(int arr[], int gap, int len)
{
    int temp;
    int i;
    int j;

    for (i = gap; i < len; ++i)
    {
        output_info(arr, len, 0);

        temp = arr[i];
        for (j = i - gap; j >= 0; j -= gap)
        {
            ++g_loop;

            if(temp < arr[j])
            {
                arr[j + gap] = arr[j];

                ++g_move;
            }
            else
            {
               break;
            }
        }

        if(j != i - gap)
        {
            arr[j + gap] = temp;
        }

        output_info(arr, len, 1);
        cout << endl;
    }
}

/* 希尔排序 */
void shell_sort(int arr[], int len)
{
    int gap;

    if (len < 2)
    {
        return;
    }

    for (gap = len / 2; gap > 0; gap /= 2)
    {
        insert_sort(arr, gap, len);
    }

    return;
}

int main()
{
    int buff[10]= {10,9,8,7,6,5,4,3,2,1};

    shell_sort(buff, 10);
    // insert_sort(buff, 1, 10);

    cout << "move=" << g_move << endl;
    cout << "loop=" << g_loop << endl;

    return 0;
}

2、测试log

before: 10 9 8 7 6 5 4 3 2 1
after:  5 9 8 7 6 10 4 3 2 1

before: 5 9 8 7 6 10 4 3 2 1
after:  5 4 8 7 6 10 9 3 2 1

before: 5 4 8 7 6 10 9 3 2 1
after:  5 4 3 7 6 10 9 8 2 1

before: 5 4 3 7 6 10 9 8 2 1
after:  5 4 3 2 6 10 9 8 7 1

before: 5 4 3 2 6 10 9 8 7 1
after:  5 4 3 2 1 10 9 8 7 6

before: 5 4 3 2 1 10 9 8 7 6
after:  3 4 5 2 1 10 9 8 7 6

before: 3 4 5 2 1 10 9 8 7 6
after:  3 2 5 4 1 10 9 8 7 6

before: 3 2 5 4 1 10 9 8 7 6
after:  1 2 3 4 5 10 9 8 7 6

before: 1 2 3 4 5 10 9 8 7 6
after:  1 2 3 4 5 10 9 8 7 6

before: 1 2 3 4 5 10 9 8 7 6
after:  1 2 3 4 5 10 9 8 7 6

before: 1 2 3 4 5 10 9 8 7 6
after:  1 2 3 4 5 8 9 10 7 6

before: 1 2 3 4 5 8 9 10 7 6
after:  1 2 3 4 5 8 7 10 9 6

before: 1 2 3 4 5 8 7 10 9 6
after:  1 2 3 4 5 6 7 8 9 10

before: 1 2 3 4 5 6 7 8 9 10
after:  1 2 3 4 5 6 7 8 9 10

before: 1 2 3 4 5 6 7 8 9 10
after:  1 2 3 4 5 6 7 8 9 10

before: 1 2 3 4 5 6 7 8 9 10
after:  1 2 3 4 5 6 7 8 9 10

before: 1 2 3 4 5 6 7 8 9 10
after:  1 2 3 4 5 6 7 8 9 10

before: 1 2 3 4 5 6 7 8 9 10
after:  1 2 3 4 5 6 7 8 9 10

before: 1 2 3 4 5 6 7 8 9 10
after:  1 2 3 4 5 6 7 8 9 10

before: 1 2 3 4 5 6 7 8 9 10
after:  1 2 3 4 5 6 7 8 9 10

before: 1 2 3 4 5 6 7 8 9 10
after:  1 2 3 4 5 6 7 8 9 10

before: 1 2 3 4 5 6 7 8 9 10
after:  1 2 3 4 5 6 7 8 9 10

move=13
loop=27

3、算法分析

  • 原地排序算法;
  • 非稳定排序算法;
  • 空间复杂度 O(1);
  • 时间复杂度 O(nlogn)。时间复杂度与增量序列选择有关。

4、优化增量序列

      采用Hibbard增量序列,时间复杂度为O(n^1.5)。 

      Hibbard增量序列=[1,3,7,15,31,63,...];

#include <iostream>
#include<math.h>

using namespace std;
int g_loop = 0;    /* 循环计数 */
int g_move = 0;    /* 数据移动次数 */

void output_info(int *buff,int len, int flag)
{
    int i;

    if(0 == flag)
    {
        cout << "before: ";
    }
    else
    {
        cout << "after:  ";
    }

    for(i = 0; i < len; ++i)
    {
        cout << *(buff + i) << " ";
    }

    cout << endl;
}

/* 插入排序 */
void insert_sort(int arr[], int gap, int len)
{
    int temp;
    int i;
    int j;

    for (i = gap; i < len; ++i)
    {
        output_info(arr, len, 0);

        temp = arr[i];
        for (j = i - gap; j >= 0; j -= gap)
        {
            ++g_loop;

            if(temp < arr[j])
            {
                arr[j + gap] = arr[j];

                ++g_move;
            }
            else
            {
               break;
            }
        }

        if(j != i - gap)
        {
            arr[j + gap] = temp;
        }

        output_info(arr, len, 1);
        cout << endl;
    }
}

//计算Hibbard增量
int get_hibbard(int count, int idx)
{
    return (int)(pow(2, count - idx + 1) - 1);
}

/* 希尔排序修改增量 */
void shell_sort(int arr[], int len)
{
    int gap;
    int i;
    int count = (int)(log(len + 1) / log(2)); /* 排序趟数 */

    if (len < 2)
    {
        return;
    }

    cout << "count=" << count << endl;

    for (i = 1; i <= count; ++i)
    {
        gap = get_hibbard(count, i);
        cout << "gap=" << gap << endl;

        insert_sort(arr, gap, len);
    }

    return;
}

int main()
{
    int buff[10]= {10,9,8,7,6,5,4,3,2,1};

    shell_sort(buff, 10);

    cout << "move=" << g_move << endl;
    cout << "loop=" << g_loop << endl;

    return 0;
}

/*************************************************************/
count=3
gap=7
before: 10 9 8 7 6 5 4 3 2 1
after:  3 9 8 7 6 5 4 10 2 1

before: 3 9 8 7 6 5 4 10 2 1
after:  3 2 8 7 6 5 4 10 9 1

before: 3 2 8 7 6 5 4 10 9 1
after:  3 2 1 7 6 5 4 10 9 8

gap=3
before: 3 2 1 7 6 5 4 10 9 8
after:  3 2 1 7 6 5 4 10 9 8

before: 3 2 1 7 6 5 4 10 9 8
after:  3 2 1 7 6 5 4 10 9 8

before: 3 2 1 7 6 5 4 10 9 8
after:  3 2 1 7 6 5 4 10 9 8

before: 3 2 1 7 6 5 4 10 9 8
after:  3 2 1 4 6 5 7 10 9 8

before: 3 2 1 4 6 5 7 10 9 8
after:  3 2 1 4 6 5 7 10 9 8

before: 3 2 1 4 6 5 7 10 9 8
after:  3 2 1 4 6 5 7 10 9 8

before: 3 2 1 4 6 5 7 10 9 8
after:  3 2 1 4 6 5 7 10 9 8

gap=1
before: 3 2 1 4 6 5 7 10 9 8
after:  2 3 1 4 6 5 7 10 9 8

before: 2 3 1 4 6 5 7 10 9 8
after:  1 2 3 4 6 5 7 10 9 8

before: 1 2 3 4 6 5 7 10 9 8
after:  1 2 3 4 6 5 7 10 9 8

before: 1 2 3 4 6 5 7 10 9 8
after:  1 2 3 4 6 5 7 10 9 8

before: 1 2 3 4 6 5 7 10 9 8
after:  1 2 3 4 5 6 7 10 9 8

before: 1 2 3 4 5 6 7 10 9 8
after:  1 2 3 4 5 6 7 10 9 8

before: 1 2 3 4 5 6 7 10 9 8
after:  1 2 3 4 5 6 7 10 9 8

before: 1 2 3 4 5 6 7 10 9 8
after:  1 2 3 4 5 6 7 9 10 8

before: 1 2 3 4 5 6 7 9 10 8
after:  1 2 3 4 5 6 7 8 9 10

move=11
loop=25

   5、排序过程图

  

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

拥抱藍天

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

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

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

打赏作者

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

抵扣说明:

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

余额充值