2.1.29

2.1.29 #

解答 #

当然是题目给出的递增序列更快啦,因为这个序列就是作者提出来的嘛。

(论文链接: http://linkinghub.elsevier.com/retrieve/pii/0196677486900015

代码 #

修改了一下 shellsort,让它按照给定的 h 序列排序。

public class ShellSort : BaseSort
{
    /// <summary>
    /// 利用希尔排序将数组按升序排序。
    /// </summary>
    /// <typeparam name="T">待排序的元素类型。</typeparam>
    /// <param name="a">待排序的数组。</param>
    /// <param name="h">需要使用的递增序列。</param>
    public void Sort<T>(T[] a, int[] h) where T : IComparable<T>
    {
        var n = a.Length;
        var t = 0;
        while (h[t] < a.Length)
        {
            t++;
            if (t >= h.Length)
                break;
        }
        t--;

        for ( ; t >= 0; t--)
        {
            for (var i = h[t]; i < n; i++)
            {
                for (var j = i; j >= h[t] && Less(a[j], a[j - h[t]]); j -= h[t])
                {
                    Exch(a, j, j - h[t]);
                }
            }
            Debug.Assert(IsHSorted(a, h[t]));
        }
        Debug.Assert(IsSorted(a));
    }

    /// <summary>
    /// 利用希尔排序将数组按升序排序。
    /// </summary>
    /// <param name="a">需要排序的数组。</param>
    public override void Sort<T>(T[] a)
    {
        var n = a.Length;
        var h = new int[2];   // 预先准备好的 h 值数组

        var hTemp = 1;
        int sequenceSize;
        for (sequenceSize = 0; hTemp < n; sequenceSize++)
        {
            if (sequenceSize >= h.Length)  // 如果数组不够大则双倍扩容
            {
                var expand = new int[h.Length * 2];
                for (var j = 0; j < h.Length; j++)
                {
                    expand[j] = h[j];
                }
                h = expand;
            }
            h[sequenceSize] = hTemp;
            hTemp = hTemp * 3 + 1;
        }

        for (var t = sequenceSize - 1; t >= 0; t--)
        {
            for (var i = h[t]; i < n; i++)
            {
                for (var j = i; j >= h[t] && Less(a[j], a[j - h[t]]); j -= h[t])
                {
                    Exch(a, j, j - h[t]);
                }
            }
            Debug.Assert(IsHSorted(a, h[t]));
        }
        Debug.Assert(IsSorted(a));
    }

    /// <summary>
    /// 检查一次希尔排序后的子数组是否有序。
    /// </summary>
    /// <param name="a">排序后的数组。</param>
    /// <param name="h">子数组间隔。</param>
    /// <returns>是否有序。</returns>
    private bool IsHSorted<T>(T[] a, int h) where T : IComparable<T>
    {
        for (var i = h; i < a.Length; i++)
        {
            if (Less(a[i], a[i - h]))
            {
                return false;
            }
        }
        return true;
    }
}

另请参阅 #

Sort 库