希尔排序
前言
希尔排序是插入排序的优化,学习希尔排序前,需要先深入理解插入排序。
以下是个人对此问题的理解;
一、简单了解希尔排序
希尔排序(Shell Sort)是插入排序的一种,它是针对直接插入排序算法的改进。
希尔排序又称缩小增量排序,因 DL.Shell 于 1959 年提出而得名。
它通过比较相距一定间隔的元素来进行,各趟比较所用的距离随着算法的进行而减小,直到只比较相邻元素的最后一趟排序为止。
二、希尔排序思路
1.思路说明:
1.希尔排序是插入排序的优化:为解决插入排序中,数据距离其正确位置较远的问题;
即优化某一个值在插入排序中需要移动较远,需多次移动的情况;
如下图中的2,按直接插入排序,需移动到现在6的位置,需经过5次移动; 如果是有80000组数据呢?是不是可能要移动几万次。 而采用希尔可以是不是只需少量的移动,元素就到了大致范围了~
2.设定一定的gap值(初始值一般为 数组.length/2),采用gap跳跃性的分组,分组后对每一组进行插入排序(保证较小的数值可以尽快排到前面,较大得值尽快到后面),完成情况1优化;
图示:
3.逐渐缩小gap值(一般每次/2),重复完成2步骤,及不断优化情况1;
图示:
4.当gap达到1,及进行一次普通插入排序,完成即可保证100%元素顺序正确;
图示:
2.与普通排序对比的个人理解:
和普通插入排序相比,增加了前几轮以一定gap排序;
但每轮排序的移动元素是有意义的,通过gap大范围移动,迅速将元素放置到大致区域,大规模减少了后续的频繁移动,并大大减少了后续的排序时比较次数。
(效率远胜于普通插入排序)。
3.实现代码:
代码如下:
public class ShellSortTest {
public static void main(String[] args) {
int [] arr={25,5,30,1,7,0,99,100,88,7};
shellSort(arr);
System.out.println(Arrays.toString(arr));
}
/**
* 思路:
* 1.希尔排序是插入排序的优化:为解决插入排序中(由小到大排序问题中),较小值位于最后面的请况;
* 即优化某一个值在插入排序中需要移动较远位置的情况;
* 2.设定一定的gap值,采用跳跃性的分组,分组后对每一组进行插入排序(保证娇小的数值可以尽快排到前面),完成情况1优化;
* 3.逐渐缩小gap值,重复完成2步骤,及不断优化情况1;
* 4.当gap达到1,及进行一次普通插入排序,完成即可保证100%元素顺序正确;
* @param arr
*/
private static void shellSort(int[] arr) {
//设定gap值为数组长度的一半,每次完成后再/2;(只是在通过跳跃性的排序,优化极端思路1中的情况)
//当值达到1时,此时为普通插入排序,可以保证100%完成正确排序;
for (int gap = arr.length/2; gap > 0; gap/=2) {
//与普通插入排序思路相同;(插入排序一定要采用移位式交换位置,效率远高于交换式)
for (int i = gap; i < arr.length; i+=gap) {
int val=arr[i];
int j=i-gap;
while (j>=0&& val<arr[j]){
arr[j+gap]=arr[j];
j-=gap;
}
//利用下标是否变化,进行优化;
//即:下表未变化,则说明不需移动位置;
if (j!=i-gap){
arr[j+gap]=val;
}
}
}
}
}