七大基于比较的排序之插入排序-希尔排序
原理(主要思想是分组)
主要思想的步骤如下:比如有15个数据,首先先分为5组,每一个小组内部进行直接插入排序,排好之后,再分为3组,每一组内部继续进行直接插入排序,排好之后,把全体看作一组,进行直接插入排序。希尔排序可以认为是直接插入排序的进化版本,因为如果数字量特别大的话,直接插入排序可能就并没有那么好了,因此我们加入希尔排序来解决这样的问题。
这里就会有一个非常严重的问题存在,这里是分组为5,3,1。如果有100个,200个数据呢?也是分为5,3,1这样吗?
在大学学习的清华大学出版社算法书中,讲到希尔排序时有一行字这么说道:“因此,到目前为止尚未有人求得一种最好的增量序列,但大量的研究已得出一些局部的结论。”,”应使增量序列中的值没有除1之外的公因子,并且最后一个增量值必须等于1.“
总结上面的话:增量值为素数最好,不是必须需要素数,但最后一个增量值必须为1.
关键的地方来了~
利用上述原理实现希尔排序(上面讲的大概就是希尔排序的主要思想,但是希尔排序并不是简单的就把前面一堆这样的数字没规律的分组,而是有计划的将一堆数字分开分组。)
希尔排序又称缩小增量法。希尔排序法的基本思想是:先选定一个整数 n,把待排序文件中所有数据分成 n 组,所有距离为 数据量 / n 的 分在同一组。并且对每一组内的数据进行排序。然后,重复上述 分组 和 排序工作。当分组的组数为 1 是,所有数据 在进行 一个排序,让数字逐步趋向有序化。
例如我们先看红色这三条线把[i]
放入temp
中,进行直接插入排序,和[j]
对比,如果temp小于[j]
则交换。交换完之后将[i]
进行++
。接下来同样的操作对绿线进行。
直接插入排序在这里就不多讲了,以前的博客里面写过,咋们直接上代码好吧!
public static int[] shell(int[]array,int gap)//array为待排序序列,gap为组数
{
for (int i=gap;i<array.length;i++)
{
int temp =array[i];
int j=i-gap;
for (;j>=0;j-=gap)
{
if (temp<array[j])
{
array[j+gap]=array[j];
}else
break;;
}
array[j+gap]=temp;
}
return array;
}
public static void shellSort(int[]array){ //生成gap
int gap=array.length;
while(gap>1){
shell(array,gap);
gap/=2;
}
shell(array,1);//保证最后是一组
}
看看一个完整的测试用例:
import java.util.*;
public class test {
public static int[] shell(int[]array,int gap)//array为待排序序列,gap为组数
{
for (int i=gap;i<array.length;i++)
{
int temp =array[i];
int j=i-gap;
for (;j>=0;j-=gap)
{
if (temp<array[j])
{
array[j+gap]=array[j];
}else
break;;
}
array[j+gap]=temp;
}
return array;
}
public static void shellSort(int[]array){ //生成gap
int gap=array.length;
while(gap>1){
shell(array,gap);
gap/=2;
}
shell(array,1);//保证最后是一组
}
public static void main(String[] args) {
int[]array={2,1,41,23,34,67,21,0,3,9,98};
shellSort(array);
int[]arrays= shell(array,1);
System.out.println(Arrays.toString(arrays));
}
}
结果: