其实这些排序的算法和代码实现早就烂大街了,为什么还要继续写?只是作为个人学习的笔记和在学了该数据结构或者算法之后有一些心得体会而已
希尔排序:
以下对希尔排序的定义来自度娘:
- 希尔排序(Shell Sort)是插入排序的一种。也称缩小增量排序,是直接插入排序算法的一种更高效的改进版本。希尔排序是非稳定排序算法。
- 希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止。
- 简单来说,希尔排序就是插入排序的改良版,到底改了哪里?其实改的地方就只把原来的数组中两两相邻两个数之间的比较换成的两个下标间隔为(增量)的数之间的比较,使得比较之后的数据不会在数组末端出现较小的数,从而减少排序次数(这里的第3点是我自己吹的~~o( ̄▽ ̄)d)
废话不多,码上见。
public class ShellSortTest {
public static void main(String[] args) {
int[] arr = {19,65,1,8,33,45,21,6,11,15,2};//定义一个需要排序的数组
sort(arr);//执行排序的方法
}
public static void sort(int[] arr){
int h = 1;//希尔排序间隔区间初始值为1,也就是上面所说的增量
while (h < arr.length) {//通过一个循环算出增量
h = h * 3 + 1;//这条公式可能是希尔他老淫家自己定的,不是我遍的
}
//偷偷告诉你,第一个while循环结束后h是13,然后下面的第一个for循环是根本进不去的,看来我该改良一下上面算h的方法
while( h > 0){//下面有增量减少的计算公式,一直减少最少去到1,也就是插入排序的两两相隔的两个数的比较了
int temp = 0;//依然是这个备胎,用来放临时的值
//注意这个i是从h开始的,就是一开始用这个下标为h的值去和其他值比较,至于和什么比较,接着看下面
for(int i = h; i < arr.length; i++){
temp = arr[i];
int j = i;//和插入排序一样,起游标作用,记录要插入的位置
//重点来了,也就是要和那个值去比较?当然和间隔为增量的值比较啦~
while( j > h - 1 && arr[j - h] > temp){
arr[j] = arr[j - h];//交换位置
j -= h;//减去一个增量,看看还有没有要比较的数据
//例如在数组:{19,65,1,8,33,45,21,6,11,15,2}中,当h等于4时,
//就只有33和19比较,然后i还是一直加加,当i=8时,就是11,33,19,三个数比较了
}
arr[j] = temp;//交换位置
}
h = (h-1)/3;//这是增量减少的公式,同样不是我瞎编的
}
//打印排序后的结果
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
}
输出结果:
1
2
6
8
11
15
19
21
33
45
65
重点:
- 为什么增量的计算公式是 h * 3 + 1 ?我个人觉得是为了把要排序的数组分为3段,前中后,这样才能把排序后的数据以小中大的形式出现,那为什么不是 h*3 ? 不知道,反正我上面用来 h * 3 , 下面用来 h/3, 加大数据量试了一下,依然可以排序
- 主要理解这里的增量就差不多了,关键点~