排序算法系列之希尔排序 (4)

希尔排序

  1. 希尔排序的巧妙之处在于把原数组拆分成 d 个子数组,其中 d 为间隔增量,使得间隔的数据之间也可以进行排序;
  2. 对每个子数组进行插入排序;
  3. 初期 d 为原数组length/2;每轮子数组都排序完毕以后, 间隔增量 d 继续除以2,继续分割子数组进行排序;
  4. 直到 d = 1的时候,也就是最后一次排序,循环结束;之前增量 d != 1 的间隔数组排序都是采用简单的插入排序算法;
  5. 希尔排序主要拆分为2部分,首先最重要的部分是对增量的更改
    /// <summary>
        /// 希尔排序:使用增量分割子数组,使得间隔的数据可以进行插入排序,直到增量递减为1,进行最后一次排序
        /// </summary>
        public void ShellSort<T>(T[] datas) where T:IComparable<T>
        {
            if (datas == null) return;
            // 初始增量为数组长度的一半
            int gap = datas.Length / 2;
            while (gap >= 1)
            {
                // 把距离为 gap 的元素编为一个组,扫描所有组
                SellInsert(datas,gap);
                // 缩小增量到1为止
                gap /= 2;
            }
        }
  6. 其次是对每次的子数组依次进行插入排序
    /// <summary>
        /// Shell希尔排序中的子数组直接插入排序 
        /// </summary>
        /// <param name="datas"> 未排序的无序数组</param>
        /// <param name="gap">分隔增量</param>
        private void SellInsert<T>(T[] datas, int gap) where T :IComparable<T>
        {
            if(datas == null) return;
            for (int i = gap, j; i < datas.Length; i++)
            {
                T tampData = datas[i];
                // 对距离为 gap 的子数据组进行简单插入排序
                for (j = i - gap; j >= 0 && tampData.CompareTo(datas[j]) <0; j -= gap)
                {
                    // 数据左右下标交换,把大数据挪到子数组的右边
                    datas[j + gap] = datas[j];
                }
                if (j != i - gap)
                {
                    // 子数据插入左端最适合的位置进行复制
                    datas[j + gap] = tampData;
                }
            }
        }
  7. 测试数据:
    string[] ShellDatas = { "a", "e", "f", "z", "G", "A", "b", "d", "F", "b", "B" };
            
            program.ShellSort(ShellDatas);
            DebugExtension.DebugArray(ShellDatas);
  8. 测试结果image
posted @ 2016-03-15 14:57  燕双飞情侣  阅读(205)  评论(0编辑  收藏  举报