一、简介和思想
希尔算法:希尔排序是插入排序的一种又称“缩小增量排序”,是简单插入排序算法的一种更高效的改进版本。希尔排序是非稳定排序算法,因 D.L.Shell 于 1959 年提出而得名。
算法的思想
希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序,随着增量逐渐减少,每组包含
的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止
图示
例如有这么个数组
int[] list = {1,5,0,64,46,54,66,11,50,2}; // 数组长度为10
初始增量=数组长度/2, gap=list.length/2,得到gap=5,那么就将这个原始数组分为5组(相同颜色用线连接的为一组)
得到这一组后、每一组的之间的元素进行比较、从小到大就小的放前面、大的放后面,然后得到。
继续进行分组 gap=gap/2 得到gap=2.5,向下取整得gap=2,分组如下
排序后
继续分组 gap=gap/2 得到 gap=1 。
再根据这一组进行排序得到如下
分步代码实现(交换法)
第一次分组排序
int[] list = {1,5,0,64,46,54,66,11,50,0};
int temp = 0;
int num =1;
// 第一次排序
// gap = 5
int gap = list.length/2;
for (int i = gap; i < list.length; i++) {
for (int j = gap; j < list.length; j++) {
if (list[j-gap]>list[j]){
temp = list[j-gap];
list[j-gap] = list[j];
list[j] = temp;
}
}
}
for(int i:list){System.out.print(i+"\t");}
System.out.println("");
第二次分步排序(在第一次分步的基础之上)
gap = list.length/2/2;
//第二次排序
for (int i = gap; i < list.length; i++) {
for (int j = gap; j < list.length; j++) {
if (list[j-gap]>list[j]){
temp = list[j-gap];
list[j-gap] = list[j];
list[j] = temp;
}
}
}
for(int i:list){System.out.print(i+"\t");}
System.out.println("");
第三次分步排序(在第一和二次分步的基础之上)
gap = list.length/2/2/2;
//第三次排序
for (int i = gap; i < list.length; i++) {
for (int j = gap; j < list.length; j++) {
if (list[j-gap]>list[j]){
temp = list[j-gap];
list[j-gap] = list[j];
list[j] = temp;
}
}
}
for(int i:list){System.out.print(i+"\t");}
System.out.println("");
总结得到、两个嵌套的for循环的内容都是一样的只有gap发生变化
得到
public static void main(String[] args) {
int[] list = {1,5,0,64,46,54,66,11,50,0};
int temp = 0;
int num =1;
int gap = list.length/2;
while(gap>0){
for (int i = gap; i < list.length; i++) {
for (int j = gap; j < list.length; j++) {
if (list[j-gap]>list[j]){
temp = list[j-gap];
list[j-gap] = list[j];
list[j] = temp;
}
}
}
System.out.println("第"+num++ +"次排序");
for (int k:list){
System.out.print(k+"\t");
}
System.out.println("");
gap/=2;
}
}
使用交换法 这个代码是老师的写的, 个人还不能理解这段代码的意思。
public static void main(String[] args) {
int[] list = {1, 5, 0, 64, 46, 54, 66, 11, 50, 0};
int num = 1;
for (int gap = list.length/2 ; gap > 0; gap/=2) {
for (int i = gap; i < list.length; i++) {
// 拿到要插入数据的下标
int j = i;
// 拿到要插入的数据
int temp = list[j];
if (list[j - gap] > temp) {
while (j - gap >= 0 && temp <list[j - gap]) {
list[j] = list[j - gap];
j -= gap;
}
list[j] = temp;
}
}
System.out.println("第" + num++ + "次排序");
for (int k : list) {
System.out.print(k + "\t");
}
System.out.println("");
}
}