简单插入排序存在的问题
数组 arr =[2,3,4,5,6,1] 这个时候我们要插入的数1,过程是这样的;
[2,3,4,5,6,6]
[2,3,4,5,5,6]
[2,3,4,4,5,6]
[2,3,3,4,5,6]
[2,2,3,4,5,6]
[1,2,3,4,5,6]当要插入的数是较小的数时,后移的次数明显增对,对效率有一定的影响。希尔排序就对简单插入排序进行了一定的优化;
希尔排序法介绍
希尔排序是希尔于1959年提出的一种排序算法。希尔排序也是一种插入排序,它是简单插入排序经过改进之后的一个更高效的版本,也称之为缩小增量排序。
希尔排序的基本思想
希尔排序是记录按下标的一定增量分组,对分组使用直接插入排序算法排序;随着增量分组逐渐减少,每组包含的关键词越来越多。当增量分组减至1时,整个文件恰被分为一组,算法便终止。
方法的实质其实时分组插入排序算法,就是对每个每组进行插入排序。
图解举例说明:
第一次分组进行排序:
将数组分为step(步长)=length/2个组 。每个组有两个元素。每个元素之间的间隔为step,即每间隔step个数的数为一组;
分为5组;相邻间隔为step的元素为同一组,索引分别为【0,5】,【1,6】,【2,7】,【3,8】,【4,9】,同一组之间的间隔为步长。 然后对同组的值进行插入排序;
排完之后的顺序为:[3 ,5 ,1 ,6 ,0 ,8 ,9 ,4 ,7 ,2]
第二次分组进行排序
第二次在第一次步长的基础上在进行分组,即step=length/2/2.
由图:10/2/2=2,分为了两组,然后对两组中的元素分别进行插入排序。
同一组的元素之间间隔step=2;索引为【0,2,4,6,8】【1,3,5,7,9】。
排完之后【0 ,2 ,1 ,4 ,3 ,5 ,7 ,6 ,9 ,8】
第三次分组进行排序
step = length/2/2/2 = 1;当增量为一1,就是最后一次排序。
直接对分组中的元素排序即可。
Java代码实现:
交换插入排序
public static void shellSort(int[] arr) {
if (arr.length!=0) {
//用来存储临时变量
int temp;
//首先分为n/2组,即每2个为一组。则每组元素之间的间隔为n/2。用step来表示步长,即同组之间的间隔。
for (int step = arr.length / 2; step > 0; step /= 2) {
//分为了n/2组,则前n/2个元素都是不同组的元素,默认第一个元素都是有序的,从每组的第二个数进行插入排序。跟同组前面有序的进行比较
//直到遍历到最后一个数
for (int i = step; i < arr.length; i++) {
//每次跟前面同组的元素进行比较
for (int j = i - step; j >= 0; j -= step) {
if (arr[j] > arr[j + step]) {
temp = arr[j];
arr[j] = arr[j + step];
arr[j + step] = temp;
}
}
}
}
}
}
后移插入排序
public static void shellSort(int[] arr) {
if (arr.length != 0) {
for (int step = arr.length / 2; step > 0; step /= 2) {
for (int i = step; i < arr.length; i++) {
int j = i;
int value = arr[j];
while (j - step >= 0 && value < arr[j - step]) {
arr[j] = arr[j - step];
j -= step;
}
arr[j] = value;
}
}
}
}