排序算法測試-希爾排序

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、排序過程圖

  

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章