备忘一下希尔排序。
原理:希尔排序是插入排序的变种。希尔排序是基于插入排序的以下两点性质而提出改进方法的:插入排序在对几乎已经排好序的数据操作时,效率高,即可以达到线性排序的效率。但插入排序一般来说是低效的,因为插入排序每次只能将数据移动一位。
借用百度百科的一段话,之所以希尔排序优于插入排序,原因是,当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
看完插入排序,希尔排序就差不多了,只是按照步长分组,分别不停地插入排序而已。
最后,如果我写的有问题,请您不吝指正。
来源:CSDN
作者:翻滚牛犊
链接:https://blog.csdn.net/Xidian185/article/details/45621183