Lesson26_希尔排序

namespace Lesson26_希尔排序
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("希尔排序");

            #region 知识点一 希尔排序的基本原理
            //希尔排序是
            //插入排序的升级版
            //必须先掌握插入排序

            //希尔排序的原理
            //将整个待排序序列
            //分割成为若干子序列
            //分别进行插入排序

            //总而言之
            //希尔排序对插入排序的升级主要就是加入了一个步长的概念
            //通过步长每次可以把原序列分为多个子序列
            //对子序列进行插入排序
            //在极限情况下可以有效降低普通插入排序的时间复杂度
            //提升算法效率
            #endregion

            #region 知识点二 代码实现
            int[] arr = new int[] { 8, 7, 1, 5, 4, 2, 6, 3, 9 };
            //学习希尔排序的前提条件 
            //先掌握插入排序
            //第一步:实现插入排序
            //第一层循环 是用来取出未排序区中的元素的
            //for (int i = 1; i < arr.Length; i++)
            //{
            //    //得出未排序区的元素
            //    int noSortNum = arr[i];
            //    //得出排序区中最后一个元素索引
            //    int sortIndex = i - 1;
            //    //进入条件
            //    //首先排序区中还有可以比较的 >=0
            //    //排序区中元素 满足交换条件 升序就是排序区中元素要大于未排序区中元素
            //    while (sortIndex >= 0 &&
            //        arr[sortIndex] > noSortNum)
            //    {
            //        arr[sortIndex + 1] = arr[sortIndex];
            //        --sortIndex;
            //    }
            //    //找到位置过后 真正的插入 值
            //    arr[sortIndex + 1] = noSortNum;
            //}

            //for (int i = 0; i < arr.Length; i++)
            //{
            //    Console.WriteLine(arr[i]);
            //}

            //第二步:确定步长
            //基本规则:每次步长变化都是/2
            //一开始步长 就是数组的长度/2
            //之后每一次 都是在上一次的步长基础上/2
            //结束条件是 步长 <=0 
            //1.第一次的步长是数组长度/2  所以:int step = arr.length/2
            //2.之后每一次步长变化都是/2  索引:step /= 2
            //3.最小步长是1  所以:step > 0
            for (int step = arr.Length / 2; step > 0; step/=2)
            {
                //注意:
                //每次得到步长后 会把该步长下所有序列都进行插入排序

                //第三步:执行插入排序
                //i=1代码 相当于 代表取出来的排序区的第一个元素
                //for (int i = 1; i < arr.Length; i++)
                //i=step 相当于 代表取出来的排序区的第一个元素
                for (int i = step; i < arr.Length; i++)
                {
                    //得出未排序区的元素
                    int noSortNum = arr[i];
                    //得出排序区中最后一个元素索引
                    //int sortIndex = i - 1;
                    //i-step 代表和子序列中 已排序区元素一一比较
                    int sortIndex = i - step;
                    //进入条件
                    //首先排序区中还有可以比较的 >=0
                    //排序区中元素 满足交换条件 升序就是排序区中元素要大于未排序区中元素
                    while (sortIndex >= 0 &&
                        arr[sortIndex] > noSortNum)
                    {
                        //arr[sortIndex + 1] = arr[sortIndex];
                        // 代表移步长个位置 代表子序列中的下一个位置
                        arr[sortIndex + step] = arr[sortIndex];
                        //--sortIndex;
                        //一个步长单位之间的比较
                        sortIndex -= step;
                    }
                    //找到位置过后 真正的插入 值
                    //arr[sortIndex + 1] = noSortNum;
                    //现在是加步长个单位
                    arr[sortIndex + step] = noSortNum;
                }
            }


            for (int i = 0; i < arr.Length; i++)
            {
                Console.WriteLine(arr[i]);
            }

            #endregion

            #region 知识点三 总结
            //基本原理
            //设置步长
            //步长不停缩小
            //到1排序后结束

            //具体排序方式
            //插入排序原理

            //套路写法
            //三层循环
            //一层获取步长
            //一层获取未排序区元素
            //一层找到合适位置插入

            //注意事项
            //步长确定后
            //会将所有子序列进行插入排序
            #endregion
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值