排序算法--希尔排序

江枫思渺然 提交于 2019-11-27 14:15:24

备忘一下希尔排序。

原理:希尔排序是插入排序的变种。希尔排序是基于插入排序的以下两点性质而提出改进方法的:插入排序在对几乎已经排好序的数据操作时,效率高,即可以达到线性排序的效率。但插入排序一般来说是低效的,因为插入排序每次只能将数据移动一位。

       借用百度百科的一段话,之所以希尔排序优于插入排序,原因是,当n值很大时数据项每一趟排序需要的个数很少,但数据项的距离很长。当n值减小时每一趟需要动的数据增多,此时已经接近于它们排序后的最终位置。 正是这两种情况的结合才使希尔排序效率比插入排序高很多。

分析:至于稳定性,单个插入能保证稳定性,但是多组插入就不能保证组之间的稳定性了,所以它是不稳定的。时间复杂度方面,好多资料认为希尔排序时间复杂度会比o(n^2)好一些。空间方面,它是原地的。

代码展示:我在这里使用的步长d初始为数组的长度的一半,然后不停减半直到1。

public class ShellSort {
	public static void main(String[] args){
		int[] target = {49,38,65,97,76,13,27,49,78,34,12,64,1};
		new ShellSort().shell_sort(target);
		System.out.print("Result:"+" ");
		for(int k : target)
			System.out.print(k+" ");
	}
	public void shell_sort(int[] target){
		if(target==null || target.length<=1)
			return;
		int d = target.length/2;//此处最初的步长我设置为待排数组长度一半
		int i=0,j=0;
		int len = target.length;
		while(true){
			for(i=0;i<d;i++){//遍历每一个组
				for(j=i;j<len;j+=d){//对每一组内的元素进行插入排序
					int tmp = target[j]; //记录当前点
					int point = j-d;//待排点前面点倒着比较
					/*
					 * 下面这个for循环备忘一下:
					 * for跳出有两种情况,一种是point小于最左边界限,明显此时应该target[point+d] = target[point];
					 * 另一种是此节点不比tmp大,也就是此节点不需要变动,肯定是它右边的需要变动,也是上面的式子
					 */
		            for(point=j-d;point>=i&&target[point]>tmp;point-=d)  
		                target[point+d] = target[point];  
		            target[point+d] = tmp;  
				}
				if(d==1)//步长为1就排一次就行了
					return;
			}
//			for(int k : target)
//				System.out.print(k+" ");
//			System.out.println();
			d /= 2;
		}
	}
}

执行结果:

Result: 1 12 13 27 34 38 49 49 64 65 76 78 97 

看完插入排序,希尔排序就差不多了,只是按照步长分组,分别不停地插入排序而已。

最后,如果我写的有问题,请您不吝指正。


易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!