【排序算法】希尔排序|细致到毛孔图解|包看懂|有代码
前言:差一点发现奇迹(可以跳过不看)
之前我看其他老哥贴的图,十分疑惑,如下图
1.第一趟实际上是两数交换,比如红色的9(索引为0)与4(索引为5),小数在前面大数在后面。【但是我以为仅仅是两数对比大小交换】
2.那么排序后形成如下图。
3.第二趟就与我想的对不上了。请注意看原图写的是gap=2(因为5/2=2),我们知道mysql里面有个叫间隙锁的东西也叫gap锁。所以gap被我认为是两数间隔的意思,比如索引为0的与索引为0+gap,也即是索引为2的为一组两两交换。
所以我按照自己的gap就是分组间隙差的理论,继续排序,天哪居然排序成功了(一开始我准备论证自己搞错的错误复盘)
那么我就要将他命名为 【间隙交换排序】作为世界第9大排序算法。 写成代码:
public void gapSort(int[] arrays) {
int length = arrays.length;
int gap = arrays.length;
while (gap > 0) {
gap /= 2;// 间隙两倍缩小
int start = 0;// 开始索引为0加一递增,最后到gap+start <= length - 1
while (start + gap <= length -1) {
if (arrays[start] > arrays[start + gap]) {
int temp = arrays[start];
arrays[start] = arrays[start + gap];
arrays[start + gap] = temp;
}
start++;
}
System.out.println(Arrays.toString(arrays));
}
System.out.println(Arrays.toString(arrays));
}
不过经过测试,这个排序算法是错误的,无法成功排序,上面的例子只是巧合,还是老老实实解释希尔排序吧。
一、希尔排序图解
我能找到的希尔排序的图,在没看懂之前是看不懂的,所以我决定自己重新画一遍,超级详细的画一遍,如下图。
我们通过对比就发现,网上这张图没有表述每组用什么排序,那可以大胆的告诉各位:就是用的冒泡排序的子排序。当然可能有其他更加专业的叫法。
二、希尔排序代码实现
希尔排序
public class shell {
public static void main(String[] args) {
shellSort(new int[]{9,1,2,5,7,4,8,6,3,5});
}
public static void shellSort(int[] a){
int group = a.length;
while (group > 0) {
group /= 2;
// 有多少组就要冒泡多少次
for (int i = 0; i < group; i++) {
// 开始冒泡
for (int j = i; j < a.length; j = j + group) {
if (j + group > a.length - 1) {
break;
}
if (a[j] > a[j + group]) {
int temp = a[j];
a[j] = a[j + group];
a[j + group] = temp;
}
}
}
System.out.println(Arrays.toString(a));
}
System.out.println(Arrays.toString(a));
}
}
冒泡排序
public void buboSort(int[] arrays) {
for (int i = 0; i < arrays.length; i++) {
for (int j = 0; j < arrays.length - i - 1; j++) {
if (arrays[j] > arrays[j + 1]) {
int temp = arrays[j + 1];
arrays[j + 1] = arrays[j];
arrays[j] = temp;
}
}
System.out.println(Arrays.toString(arrays));
}
System.out.println(Arrays.toString(arrays));
}
总结
我们将与希尔排序与冒泡排序进行对比
代码复杂度 | 时间复杂度 | 关系 | |
---|---|---|---|
希尔排序 | 比较复杂 | n*log(n) | 分组后组内排序用到了冒泡思想,所以循环时是j = j + group |
冒泡排序 | 简单 | n*n | 冒泡排序是相邻元素之间的对比交换,所以循环时是j++ |