排序算法:希尔排序

希尔排序:不稳定排序

希尔排序(Shell Sort)是插入排序的一种。也称缩小增量排序,是直接插入排序算法的一种更高效的改进版本。

先取一个小于n的整数d1作为第一个增量,把文件的全部记录分组。所有距离为d1的倍数的记录放在同一个组中。先在各组内进行直接插入排序;然后,取第二个增量d2<d1重复上述的分组和排序,直至所取的增量

   
=1(
   
<
   
…<d2<d1),即所有记录放在同一组中进行直接插入排序为止。

一般的初次取序列的一半为增量,以后每次减半,直到增量为1。

比较相隔较远距离(称为增量)的数,使得数移动时能跨过多个元素,则进行一次比较就可能消除多个元素交换。不像直接插入多次比较才能插入一个元素。


希尔排序的时间复杂度与增量序列的选取有关,例如希尔增量时间复杂度为O(n²),而Hibbard增量的希尔排序的时间复杂度为O(

   
),希尔排序时间复杂度的下界是n*log2n。希尔排序没有 快速排序算法 快 O(n(logn)),因此中等大小规模表现良好,对规模非常大的 数据排序 不是最优选择。但是比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));
	}
	
}


猜你喜欢

转载自blog.csdn.net/linyk3/article/details/48178669