C# 实现希尔排序

C# 实现希尔排序

过程拆解

假设现有一数组,如下

在这里插入图片描述
基本排序代码,如下

static void Main(string[] args)
{
    int[] array = new int[] { 5, 4, 5, 2, 3, 6, 1 };//替换代码
    BaseSort(array, 3);//替换代码
    for (int i = 0; i < array.Length; i++)
    {
        Console.Write(array[i] + " ");
    }
    Console.ReadKey();
}
public static void BaseSort(int[] array, int gap)
{
    for (int i = gap; i < array.Length; i++)
    {
        int insertValue = array[i];
        for (int j = i - gap; j >= 0; j -= gap)
        {
            if (insertValue < array[j])
            {
                array[j + gap] = array[j];
                array[j] = insertValue;
            }
            else
            {
                break;
            }
        }
    }
}
  1. 替换代码换成下列代码,运行并分析
int[] array = new int[] { 5, 4, 5, 2, 3, 6, 1 };
BaseSort(array, 3);
//将下标差值为 3 的一组数进行排序

下标 3 向前找出 间隔为3 的数 下标 0,并使用插入排序算法进行排序。

在这里插入图片描述
下标 4 向前找出 间隔为3 的数 下标 1,并使用插入排序算法进行排序。
在这里插入图片描述
下标 5 向前找出 间隔为3 的数 下标 2,并使用插入排序算法进行排序。
在这里插入图片描述
下标 6 向前找出 间隔为3 的数 下标 3下标 0,并且此时下标 0 与下标 3 已经排好序,再使用插入排序算法进行排序。
在这里插入图片描述

  1. 替换代码换成下列代码,运行并分析
int[] array = new int[] { 1, 3, 5, 2, 4, 6, 5 };
BaseSort(array, 1);
//将下标差值为 1 的一组数进行排序

下标 1 向前找出 间隔为1 的数 下标 0,并进行插入排序算法进行排序。
在这里插入图片描述
下标 1 向前找出 间隔为1 的数 下标 1、下标 0,并进行插入排序算法进行排序。
在这里插入图片描述
下标 1 向前找出 间隔为1 的数 下标 2、下标 1、下标 0,并进行插入排序算法进行排序。
在这里插入图片描述
下标 1 向前找出 间隔为1 的数 下标 3、下标 2、下标 1、下标 0,并进行插入排序算法进行排序。
在这里插入图片描述
下标 1 向前找出 间隔为1 的数 下标 4、下标 3、下标 2、下标 1、下标 0,并进行插入排序算法进行排序。
在这里插入图片描述
下标 1 向前找出 间隔为1 的数 下标 5、下标 4、下标 3、下标 2、下标 1、下标 0,并进行插入排序算法进行排序。
在这里插入图片描述

算法实现

  1. 希尔排序利用间隔进行分组排序,对直接插入排序算法进行了优化
  2. 选择数组长度的一半作为初始间隔长度,并将它们进行排序,之后循环取 n / 2 作为间隔。
  3. 尽可能的让最后一次执行直接插入排序的时间算法复杂度为O(n)。

代码如下

static void Main(string[] args)
{
    int[] array = new int[] { 5, 4, 5, 2, 3, 6, 1 };
    ShellSort(array);
    for (int i = 0; i < array.Length; i++)
    {
        Console.Write(array[i] + " ");
    }
    Console.ReadKey();
}
public static void ShellSort(int[] array)
{
    for (int gap = array.Length / 2; gap > 0; gap /= 2)
    {
        //直接插入排序算法
        for (int i = gap; i < array.Length; i++)
        {
            int insertValue = array[i];
            for (int j = i - gap; j >= 0; j -= gap)
            {
                if (insertValue < array[j])
                {
                    array[j + gap] = array[j];
                    array[j] = insertValue;
                }
                else
                {
                    break;
                }
            }
        }
    }
}

拆分的代码如下

public static void ShellSort(int[] array)
{
    for (int gap = array.Length / 2; gap > 0; gap /= 2)
    {
        InsertSort(array, gap);
    }
}

public static void InsertSort(int[] array, int gap)
{
    for (int i = gap; i < array.Length; i++)
    {
        int insertValue = array[i];
        for (int j = i - gap; j >= 0; j -= gap)
        {
            if (insertValue < array[j])
            {
                array[j + gap] = array[j];
                array[j] = insertValue;
            }
            else
            {
                break;
            }
        }
    }
}

复杂度与稳定性

在这里插入图片描述

  • 最优时间复杂度:当间隔为1,且排好序的情况,只需要经历插入排序中第1个 for循环
  • 最差时间复杂度:当数组是倒序的,通过希尔排序中的间隔操作后,可以减少插入排序中第2个 for循环 的执行次数。因此实际排序的时间与直接插入排序的最差时间复杂度是一样的。
  • 平均时间复杂度:主要取决于间隔的取值
  • 空间复杂度:需要借助 insertValue 变量用来记录进行比较的数值
  • 稳定性:经过排序算法后,前面的数值排在了后面(如:5)

因为作者精力有限,文章中难免出现一些错漏,敬请广大专家和网友批评、指正。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值