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

希尔排序:

希尔排序是对插入排序的优化,将插入排序的交换步长由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;
}
}

}

}

原文地址:https://www.cnblogs.com/sdx-BK/p/12053772.html