• 常见排序算法——希尔排序


    希尔排序:

    希尔排序是对插入排序的优化,将插入排序的交换步长由1增加到h。
    希尔排序的思想是使数组中任意间隔为h的元素有序。步长调幅为h = 3*h + 1, 也就是1,4,13,40,121,364, 1003....这种步长算法是经过论文证明为比较高效的步长。
    最开始由最大步长开始排序,最大步长为
    while(h < n/3) h = 3*h +1
    步长最大时,比较的元素非常少,速度很快
    后来步长逐渐缩短,比较的元素越来越多,但是此时元素的有序性也变好了,排序速度还是会很快。
    while(h>=1){
      for: i from h~n{
        for: j from i~h,j = j-h;
          比较a[j]和a[j-h],并根据比较结果交换元素位置,
      }
    }
     

    实现代码:()
    import java.util.Arrays;

    import java.util.Random;

    public class ShellSort {

    1.这是定义了一个公共的(public)静态的(static )泛型方法
    其中<AnyType extends Comparable<? super AnyType>>是泛型的类型,定义类型只能是Comparable或Comparable的子类,并且Comparable也是一个泛型类他的 类型只能是AnyType或是AayType的超类也就是AayType父类
    int 是方法的返回类型
    (AnyType[] a,AnyType x)参数列表,第一个是传递进来的数组第二个是一个值,也就是查找该值在数组中的下标,他们的类型都是该泛型方发传进来的类型
    public static <AnyType extends Comparable<? super AnyType>>

    void shellSortOnce(AnyType a[]){

    AnyType temp;

    if((a==null)||(a.length==0)){

    return ;

    }

    for(int gap = a.length /2 ; gap > 0 ;gap = gap /2){

    for(int i = gap ; i<a.length; i++){

    AnyType tmp = a[i];

    int j = i;

    for( ; j >= gap && tmp.compareTo(a[j - gap]) < 0 ; j -= gap){

    a[j] = a[j-gap];

    }

    a[j] = tmp ;

    }

    }

    }

    public static void main(String[] args){

    Random rand = new Random();

    Integer[] arr = new Integer[10];

    for(int i = 0 ;i <10 ;i++){

    arr[i] = rand.nextInt(1000);

    }

    println(Arrays.toString(arr));

    shellSortOnce(arr);

    println(Arrays.toString(arr));

    }

    public static void println(String str){

    System.out.println(str);

    }
    }
    }

    import java.util.Arrays;

    import com.edu.hpu.sort.Sort;

    public class ShellSort extends Sort {

    @Override

    public int[] doSort(int[] arr) {

    int len = arr.length;

    // 所有的步长可能性(首次为数组长的一半,接下来每次为上一次的一半)
    for (int gap = len / 2; gap > 0; gap /= 2) {

    // 将步长中的所有元素进行插入排序
    for(int w = 0; w < gap; w++){

    // 步长为gap的插入排序

    // 对照插入排序
    /*
    * for(int i = p + 1; i < r; i++){

    * int key = arr[i];

    * int j = i - 1;

    * while(j >= 0 && arr[j] > key) {

    * arr[j + 1] = arr[j];

    * j--;

    * }

    * arr[j + 1] = key;

    * }

    */
    for (int i = gap + w; i < len; i += gap) {

    // 插入排序
    int key = arr[i];

    int j = i - gap;

    while (j >= 0 && arr[j] > key) {

    arr[j + gap] = arr[j];

    j -= gap;

    }

    arr[j + gap] = key;

    }

    }

    System.out.println(Arrays.toString(arr));

    }

    return arr;

    }

    public static void main(String[] args) {

    Sort sort = new ShellSort();

    sort.printOrder(new int[] {100, 201, 999, 4, 1, 3, 2, 16, 9, 100, 194, 8, 7, 0, 90 });

    }
    }
    }

    package www.jk.shell;

    import java.util.Arrays;

    public class Test {

    /**
    * @author jk,这个代码写的是shell排序,其实我个人认为这个排序的思想是把归并和快排的思想结合起来,快排是通过
    * 第一个元素来进行左右划分,归并是无论什么样,先将数组分成两组,然后继续分最后结合起来,这个shell排序,首先是将数组
    * 分为两组,然后进行插入,其实就类似将大的或者小的先放在前面或者后面,所以,我认为这个算法的复杂度应该和归并和快排是差不多的
    *
    */
    public static void main(String[] args) {
    int[] a = { 1, 4, 2, 0, 8, 6, 4, 6 };
    shellSort(a);
    // 输出排序后的数组
    System.out.println(Arrays.toString(a));

    }

    private static void shellSort(int[] a) {
    // 将数组分组
    for (int r = a.length / 2; r >= 1; r /= 2) {
    // 这里的思路和插入排序的思路相同,通过找到前一个的数大于或者小于来进行插入
    for (int i = r; i < a.length; i += r) {
    int temp = a[i];
    int j = i - r;
    while (j >= 0 && temp < a[j]) {
    a[j + r] = a[j];
    j -= r;
    }
    a[j + r] = temp;
    }
    }

    }

    }

  • 相关阅读:
    使用ACEGI搭建权限系统:第三部分
    分支在版本树中的应用(使用subversion)
    acegi安全框架使用:第二部分
    错误数据导致java.lang.IllegalArgumentException:Unsupported configuration attributes
    移动中间件和wap网关的比较
    3年后,又回到了.net阵营
    android中listView的几点总结
    oracle相关分布式数据解决方案
    ajax实现用户名存在校验
    使用template method模式简化android列表页面
  • 原文地址:https://www.cnblogs.com/sdx-BK/p/12053772.html
Copyright © 2020-2023  润新知