希尔排序:不稳定排序
希尔排序(Shell Sort)是插入排序的一种。也称缩小增量排序,是直接插入排序算法的一种更高效的改进版本。
先取一个小于n的整数d1作为第一个增量,把文件的全部记录分组。所有距离为d1的倍数的记录放在同一个组中。先在各组内进行直接插入排序;然后,取第二个增量d2<d1重复上述的分组和排序,直至所取的增量
一般的初次取序列的一半为增量,以后每次减半,直到增量为1。
比较相隔较远距离(称为增量)的数,使得数移动时能跨过多个元素,则进行一次比较就可能消除多个元素交换。不像直接插入多次比较才能插入一个元素。
希尔排序的时间复杂度与增量序列的选取有关,例如希尔增量时间复杂度为O(n²),而Hibbard增量的希尔排序的时间复杂度为O(
package test; import java.util.Arrays; /* * 希尔排序: * 把数组按照增量分组,分别对每个分组进行直接插入排序。 * 在新的数组中缩小增量,继续分组排序,直到增量为1. * 这样就可以将数组中的元素排好序了。 * * 希尔排序是改进的插入排序。 * 直接插入排序在需要经过多次的比较才可应交换一个元素 * 希尔排序经过分组,可以实现在一次比较中交换多个元素 * 时间复杂度与增量选择有关,最差是O(nlog2n),比直接插入的O(n^2)好 */ public class shellSort { //希尔排序:首先将数组按增量s分组,在每一个分组进行直接插入排序 static void ShellSort(int a[], int len) { //初始增量s取值为len/2,逐渐缩小增量,直到增量为1表示已经全部排好序 for(int s = len/2; s >= 1; s /= 2) { //增量为s,那么就有s个分组。对每个分组进行排序 for(int i = 0; i < s; i++ ) { sort(a,i,s,len); } } } //对每个分组进行直接排序,基本实现与直接插入一致,只是下标增量为s,不是为1 //其中i表示分组的起始小标,s表示增量 static void sort(int a[], int i, int s, int len) { //默认分组第一个元素A[i]是排好序的,从分组的第二个元素A[i+s]开始进行插入排序 for(int j = i+s; j < len; j += s) { //如果待插入元素小于排好序部分的最后一个元素,表明待插入元素不是直接插入排好序部分的后面 if(a[j] < a[j-s]) { //记录待插入元素 int temp = a[j]; //需要将排好序的部分从后往前都右移一位,直到找到比待插入元素小的元素 while(j-s >= 0 && a[j-s] > temp) { //元素往后移动一位 a[j] = a[j-s]; j -= s; } //将待插入元素插入 a[j] = temp; } } } public static void main(String args[]) { int a[] = new int[]{4,2,6,8,3,7,9,333,555,22,4,6,88,4,3,4456,32,7,8,64}; ShellSort(a,a.length); System.out.println(Arrays.toString(a)); } }