Shell排序

zhj12399發表於2020-12-18

增量每次除以2遞減的

程式

void ModInsSort(int array[], int n, int delta)
{
    for (int i = delta; i < n; i += delta)
    {
        for (int j = i; j >= delta; j -= delta)
        {
            if (array[j] < array[j - delta])
            {
                swap(array, j, j - delta);
            }
            else
            {
                break;
            }
        }
    }
}

void ShellSort(int array[], int n)
{
    //增量delta每次除以2遞減
    for (int delta = n / 2; delta > 0; delta /= 2)
    {
        for (int i = 0; i < delta; i++)
        {//分別對delta個子序列進行插入排序,&array[i]傳的是地址,陣列總長度為n-1
            ModInsSort(&array[i], n - i, delta);
        }
    }
    //如果增量序列不能保證最後一個delta間距為1
    //可以安排下面這個掃尾性質的插入排序
    // ModInsSort(array,n,1);
}

原理

首先delta為半個陣列,實現跨域陣列的插入排序
在這裡插入圖片描述
在這裡插入圖片描述
第一步排序結束後,delta值除以2,即現在每次進行插入排序的個數翻倍變成4
在這裡插入圖片描述
在這裡插入圖片描述
第二步結束後,下一步就變成了全部再來一遍插入排序
在這裡插入圖片描述
在這裡插入圖片描述
但這樣排序的時間代價是0(n^2),原因是每次還是會有重複出現的數進行排序,上一輪間距為2^k-1的子序列都是有那些間距為2^k的子序列組成的,上一輪迴圈中這些子序列已經排過序了
所以我們需要選擇特殊的增量序列

其它形式的Shell排序

Hibbard增量序列

{2^k - 1, 2^(k-1) - 1, ..., 7, 3, 1}
或者採用增量除以3,Shell(3)的序列來排序
這樣的序列效率都可以達到0(n^(3/2))

Shell最好的代價

2^p*3^q形式的一系列整數
1, 2, 3, 4, 6, 8, 9, 12
這樣的排序效率為0(n*log2(n))

相關文章