美文网首页
希尔排序

希尔排序

作者: Stroman | 来源:发表于2018-02-02 21:16 被阅读5次
    package com.company;
    
    public class ShellSort {
        /**
         * 希尔排序其实是插入排序的变种
         * 在这里姑且先用非递归排序实现
         * 此算法
         * 只不过它有步长的设定
         * 即,根据步长来对整个数组进行分组
         * 不过每个分组中的元素都是间距相同
         * 的两个元素
         * 然后对每组进行排序
         * 其实也是分而治之算法的体现
         * @param sourceArray
         */
        static public void shellSort0(int[] sourceArray) {
            int arrayLength = sourceArray.length;
            //一开始的步长。
            int stepWidth = arrayLength;
            //因为最后的步长肯定会变成1的
            //这也就意味着最后一次排序的进行了
            while (stepWidth > 1) {
                //姑且把步长设置为原来步长的1/2吧
                stepWidth /= 2;
                //打印
                System.out.println("步长为" + stepWidth);
                //我之所以这样写是因为我觉得
                //1、步长会越来越小
                //2、所有步长相邻的元素都可以从开始
                //被遍历到。
                //但是这样写会使整个实现变得很长
                for (int counter = 0;counter < stepWidth;counter++) {
                    //现在开始进行一小趟的排序
                    //通过插入排序法对每个元素进行排序
                    //需要被插入的index
                    int stepIndex = 1;
                    //这个元素的index不能超出数组范围
                    while (counter + stepIndex * stepWidth < arrayLength) {
                        int insertIndex = counter + stepIndex * stepWidth;
                        //先保存这个待插入的元素值
                        int tempElement = sourceArray[insertIndex];
                        //元素该插入的位置。
                        int targetIndex = counter;
                        for (int counter0 = counter;counter0 < counter + stepIndex * stepWidth;counter0+=stepWidth) {
                            if (tempElement > sourceArray[counter0]) {
                                targetIndex = counter0;
                                //移动元素
                                for (int counter1 = insertIndex;counter1 > targetIndex;counter1-=stepWidth)
                                    sourceArray[counter1] = sourceArray[counter1 - stepWidth];
                                //插入元素
                                sourceArray[targetIndex] = tempElement;
                                break;
                            } else continue;
                        }
                        //打印每一分组的元素状况。
                        for (int element:sourceArray) {
                            System.out.print(element + " ");
                        }
                        System.out.println("第" + stepIndex + "次交换结束了");
                        stepIndex++;
                    }
                    //打印每一趟的元素状况。
                    for (int element:sourceArray) {
                        System.out.print(element + " ");
                    }
                    System.out.println("第" + (counter + 1) + "趟结束了\n");
                }
            }
        }
    
        /**
         * 上面的方法写得过于冗长
         * 本方法是参照了网上的版本
         * 把代码写得精简了一些
         * @param sourceArray
         */
        static public void shellSort1(int[] sourceArray) {
            int arrayLength = sourceArray.length;
            //上面那个while循环完全可以写成for循环
            for (int stepWidth = arrayLength / 2;stepWidth >= 1;stepWidth /= 2){
                //因为上面的方法比较长,所以此处需要改写。
                //毕竟插入排序算法是从第2个元素开始的
                //其实就相当于步长为1了
                //而现在是步长是大于了
                //那么就是说可以从1*stepWidth开始
                //下面这样写是把插入和遍历整个数组的思想结合起来了
                //这种写法的宏观着眼点是针对每个元素采取不同的方式来处理
                //我上面的着眼点是一个个单独的相邻步长的元素
                //我上面的写法总是直接切入没拐弯
                for (int counter = stepWidth;counter < arrayLength;counter++) {
                    //这个还是保存需要被插入的元素值
                    int tempElement = sourceArray[counter];
                    //这样就把下标变成从0开始了
                    int counter0 = counter - stepWidth;
                    //它是从后往前遍历,只要不满足这个条件就代表找到位置了
                    //而我是从前往后正向遍历——很麻烦!
                    //从后往前写给人的感觉思路非常清晰
                    //并且这样遍历到每个元素,它之前的元素
                    //都已经是排好序的了
                    while (counter0 >= 0 && tempElement > sourceArray[counter0]) {
                        sourceArray[counter0 + stepWidth] = sourceArray[counter0];
                        counter0 -= stepWidth;
                    }
                    sourceArray[counter0 + stepWidth] = tempElement;
                }
                //打印每一趟的元素状况。
                for (int element:sourceArray) {
                    System.out.print(element + " ");
                }
                System.out.println("步长 " + stepWidth + " 的趟结束了\n");
            }
        }
    }
    

    相关文章

      网友评论

          本文标题:希尔排序

          本文链接:https://www.haomeiwen.com/subject/zjqyzxtx.html