zoukankan      html  css  js  c++  java
  • 算法一小时--希尔排序

    在写希尔排序之前,首先我对之前的Java代码进行了优化。

    之前的代码中由于Comparable<T>中的T都是用的String,因此在写一个测试方法时,必须对输入的数字进行转换,十分麻烦。 因此我将方法都写成了泛型的写法:

    package com.jacob.demo;
    
    /**
     * This is a sample for sort algorithms.
     * @author jacob
     *
     */
    public class Example {
        
        /**
         * The function for sort.
         * @param a
         */
        public static<T> void sort(Comparable<T>[] a) {
            
        }
        
        /**
         * Compare if v is less than w.
         * @param v
         * @param w
         * @return
         */
        public static<T> boolean less(Comparable<T> v, Comparable<T> w) {
            return v.compareTo((T) w) < 0;
        }
        
        /**
         * exchange two elements.
         * @param a
         * @param i
         * @param j
         */
        public static<T> void exch(Comparable<T>[] a, int i, int j) {
            Comparable<T> t = a[i];
            a[i] = a[j];
            a[j] = t;
        }
        
        /**
         * Print array.
         * @param a
         */
        private static<T> void show(Comparable<T>[] a) {
            for (int i= 0; i< a.length; i++) {
                System.out.print(a[i] + " ");
            }
            System.out.println();
        }
        
        /**
         * Judge if array is sorted
         * @param a
         * @return
         */
        public static<T> boolean isSorted(Comparable<T>[] a) {
            for (int i = 1; i < a.length; i++) {
                if (less(a[i], a[i-1])) {
                    return false;
                }
            }
            
            return true;
        }
        
        public static void main(String[] args) {
            String[] a = {"S","O","R","T","E","X","A","M","P","L","E"};
            System.out.println("Before sort:");
            show(a);
            
            System.out.println("sort begin:");
            sort(a);
            assert isSorted(a);
        }
    }

    之后的代码也会采用该模板。

    言归正传。

    1. 希尔排序的实现思路

    希尔排序是基于插入排序改进出来的一种排序方法。 对于插入排序来说,当遇到大规模乱序数组的时候,速度是比较慢的,因为它只会交换相邻的元素,因此元素只能一个一个从数组一端移动到另一端,上一篇的例子中是从末尾移动到对应的位置。

    希尔排序为了加快速度,改进了插入排序。它将数组根据间隔元素数h分成了几个小数组,然后对这些小数组进行局部插入排序,然后递减h,最终将这些全部排序。

    例如:

    Before sort:

    S H E L L S O R T E X A M P L E         //初始数组

    sort begin:

    //第一次分组,间隔h取13

    [P] [H] [E] [L] L S O R T E X A [M] [S] [L] [E]   //第一次排序结束

    a loop is over; h is 13

    // 第二次分组,h 取 4

    [L] H E L [P] S O R [T] E X A [M] S L E      // 对 P L T M 进行插入排序

    [L] H E L [P] S O R [T] E X A [M] S L E       

    [L] H E L [P] S O R [T] E X A [M] S L E     

    [L] H E L [P] S O R [T] E X A [M] S L E    

    [L] H E L [P] S O R [T] E X A [M] S L E      

    L [E] E L P [H] O R T [S] X A M [S] L E    // 对 H S E S 进行插入排序

    L [E] E L P [H] O R T [S] X A M [S] L E 

    L [E] E A P [H] O L T [S] X R M [S] L E 

    L [E] E A M [H] O L P [S] X R T [S] L E 

    L E [E] A M H [O] L P S [X] R T S [L] E      //对E O X L j进行插入排序

    L E [E] A M H [L] L P S [O] R T S [X] E 

    L E E [A] M H E [P] S O L [T] S X R          //对A P T 进行插入排序 

     

    // 第三次分组,h取1, 此时就是对数组进行一次插入排序

    E L E A M H L E P S O L T S X R 

    E E L A M H L E P S O L T S X R 

    A E E L M H L E P S O L T S X R 

    A E E L M H L E P S O L T S X R 

    A E E H L M L E P S O L T S X R 

    A E E H L L M E P S O L T S X R 

    A E E E H L L M P S O L T S X R 

    A E E E H L L M P S O L T S X R 

    A E E E H L L M P S O L T S X R 

    A E E E H L L M O P S L T S X R 

    A E E E H L L L M O P S T S X R 

    A E E E H L L L M O P S T S X R 

    A E E E H L L L M O P S S T X R 

    A E E E H L L L M O P S S T X R 

    A E E E H L L L M O P R S S T X 

    //排序结束

     

    根据上述的希尔排序的实现思路,实现代码如下:

     

    /**
         * The function for sort.
         * @param a
         */
        public static<T> void sort(Comparable<T>[] a) {
            int h = 1;
            int N = a.length;
            
            while(h < N/3) {
                h = 3*h + 1;
            }
            
            while(h >=1) {
                for(int i = h; i < N; i++) {
                    for(int j= i; j >= h && less(a[j], a[j-h]); j-=h) {
                        exch(a, j, j-h);
                    }
                    show(a);
                }
                
                System.out.println("a loop is over; h is " + h);
                h=h/3;
            }
        }

    希尔排序更高效的原因是它权衡了子数组的规模和有序性。

    另外,选择h也是一个难点,一般取决于其数学性质,如公因子等。

    JS的实现

    根据希尔排序的实现原理,JS的实现代码如下:

    function shell(array) {
    
        let h = 1;
    
        // splite array to serveral arraies with h elements.
        while(h < array.length / 3) {
            h = 3*h +1;
        }
    
        // insertion for h elements array.
        while(h >= 1) {
            for(i = h; i < array.length; i++) {
                for(j = i; j >= h && array[j] < array[j-h]; j-=h ) {
                    exch(array, j-h, j);
                }
                console.log(array);
            }
            console.log("a loop is done, h is " + h);
            h=parseInt(h/3);
            
        }
    
    }
    
    function exch(array, firstIndex, minIndex) {
        let temp = array[firstIndex];
        array[firstIndex] = array[minIndex];
        array[minIndex] = temp;
    }
    
    function main() {
        var arr = [5,3,7,1,7,8,1];
        console.log(arr);
        shell(arr);
        console.log("after sort");
        console.log(arr);
    }
    
    main();

  • 相关阅读:
    BW中变量增强学习
    视频压制参数设置详细说明(转)
    swf文件格式解析(二)
    关于FP10.2的自定义鼠标功能
    swf文件格式解析(一)
    如何判断winform程序已安装过
    flashbuilder4.5 作为eclipse插件
    安装程序无法创建新的系统分区,也无法定位现有系统分区 (转载于百度文库)
    【转】VS2008建造打包法度将安装路径写入注册表
    【高清视频压制教程】使用MeGUI压制视频教程(以PSP视频为例)(转载)
  • 原文地址:https://www.cnblogs.com/JacobQiao/p/9378681.html
Copyright © 2011-2022 走看看