希尔排序笔记
Posted 是渣渣呀
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了希尔排序笔记相关的知识,希望对你有一定的参考价值。
希尔排序(算法)
基本介绍
简单插入排序存在的问题:
我们看简单的插入排序可能存在的问题.
数组 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
结论:当 需要插入的数是较小的数时, 后移的次数明显增多,对 效率有影响.
希尔排序是希尔(Donald Shell)于 1959 年提出的一种排序算法。希尔排序也是一种 插入排序,它是简单插入
排序经过改进之后的一个 更高效的版本,也称为 缩小增量排序。
算法思想与图解
希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含
的关键词越来越多, 当增量减至 1 时,整个文件恰被分成一组,算法便终止
代码实现
有一群小牛, 考试成绩分别是 8,9,1,7,2,3,5,4,6,0 请从小到大排序. 请分别使用
- 希尔排序时, 对有序序列在插入时采用 交换法, 并测试排序速度.
- 希尔排序时, 对有序序列在插入时采用 移动法, 并测试排序速度
注: main方法里注释掉的代码是用来测试该算法所用时间的
public class ShellSort
public static void main(String[] args)
int[] arr = 8,9,1,7,2,3,5,4,6,0;
System.out.println("排序前:");
System.out.println(Arrays.toString(arr));
// int[] arrTest = new int[80000];
// for (int i = 0; i < arrTest.length; i++)
// arrTest[i] = (int)(Math.random()*80000); //生成一个【0,80000】的数
//
// Date date1 = new Date();
// SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM--dd HH:mm:ss");
// String date1Str = simpleDateFormat.format(date1);
// System.out.println("排序前的时间是="+date1Str);
// shellSort(arrTest); //测试交换式希尔排序的时间
// shellSort(arr); // 交换式的希尔排序
// shellSort2(arrTest); //测试移动式希尔排序的时间
shellSort2(arr); //移位式的希尔排序
System.out.println("排序后:");
System.out.println(Arrays.toString(arr));
// Date date2 = new Date();
// SimpleDateFormat simpleDateFormat2 = new SimpleDateFormat("yyyy-MM--dd HH:mm:ss");
// String date2Str = simpleDateFormat2.format(date2);
// System.out.println("排序后的时间是="+date2Str);
//交换法
// 希尔排序时, 对有序序列在插入时采用交换法,
// 思路(算法) ===> 代码
public static void shellSort(int[] arr)
int temp = 0;
int count = 0;
//根据逐步分析,使用循环处理
for (int gap = arr.length / 2; gap > 0 ; gap /= 2)
for (int i = gap; i < arr.length; i++)
// 遍历各组中所有的元素(共 gap 组,每组有 个元素), 步长 gap
for (int j = i - gap; j >= 0; j -= gap)
// 如果当前元素大于加上步长后的那个元素,说明交换
/*
注: 下面这个if语句里一定不能把 j+gap 写成 i
因为第三层for循环里 是为了把当前一组的元素 的大小顺序给排好
当 i 的值小的时候,能比较的元素个数也少, 当i逐渐加到最大时, 各个组(注:是不同的组)的顺序会排好
举例: 当gap = 2(即第二次希尔排序)时,
i一开始为2 , 所以只能arr[0] 和 arr[2]比较
接着为3 , arr[1] arr[3] (1,3为一组)
4 arr[2]和arr[4] 、 arr[0]和arr[2] (0,2,4为一组)
(注: 这时,0,2,4之间的顺序是排好了的,1、3也是)
到了最后一个元素时,各个组内部就都拍好了序
。。。。。。。。。
*/
if (arr[j] > arr[j+gap])
temp = arr[j];
arr[j] = arr[j+gap];
arr[j+gap] = temp;
//System.out.println("希尔排序第"+(++count)+"一轮后="+ Arrays.toString(arr));
//使用逐步推导的方式编写
// int temp = 0;
// //希尔排序的第一轮,是将10个数据分成了5组 (10/2)
// for (int i = 5; i < arr.length; i++)
// // 遍历各组中所有的元素(共 5 组,每组有 2 个元素), 步长 5
// for (int j = i - 5; j >= 0; j -= 5)
// // 如果当前元素大于加上步长后的那个元素,说明交换
// if (arr[j] > arr[j+5])
// temp = arr[j];
// arr[j] = arr[j+5];
// arr[j+5] = temp;
//
//
//
// System.out.println("希尔排序第一轮后="+ Arrays.toString(arr));
//
// //希尔排序的第二轮,是将10个数据分成了5/2 = 2组
// for (int i = 2; i < arr.length; i++)
// // 遍历各组中所有的元素(共 2 组,每组有 5 个元素), 步长 2
// for (int j = i - 2; j >= 0; j -= 2)
// // 如果当前元素大于加上步长后的那个元素,说明交换
// if (arr[j] > arr[j+2])
// temp = arr[j];
// arr[j] = arr[j+2];
// arr[j+2] = temp;
//
//
//
// System.out.println("希尔排序第二轮后="+ Arrays.toString(arr));
//
// //希尔排序的第三轮,是将10个数据分成了2/2 = 1组
// for (int i = 1; i < arr.length; i++)
// // 遍历各组中所有的元素(共 1 组,每组有 10 个元素), 步长 1
// for (int j = i - 1; j >= 0; j -= 1)
// // 如果当前元素大于加上步长后的那个元素,说明交换
// if (arr[j] > arr[j+1])
// temp = arr[j];
// arr[j] = arr[j+1];
// arr[j+1] = temp;
//
//
//
// System.out.println("希尔排序第三轮后="+ Arrays.toString(arr));
//对交换式的希尔排序进行优化 -> 移位法
public static void shellSort2(int[] arr)
//增量gap, 并逐步的缩小增量
for (int gap = arr.length / 2; gap > 0 ; gap /= 2)
// 从第 gap 个元素, 逐个对其所在的组进行直接插入排序
for (int i = gap; i < arr.length; i++)
int j = i; //存放要插入元素的下标, 最终表示最后要插入位置的下标
int temp = arr[j]; //存放要插入元素的值
//跟插入排序算法类似,要找到元素最终插入的位置 (但要注意 步长)
while (j - gap >= 0 && temp < arr[j-gap])
//移动
arr[j] = arr[j-gap];
j -= gap;
//当退出while循环时,说明已经给temp找到了插入的位置
arr[j] = temp;
运行结果
排序前:
[8, 9, 1, 7, 2, 3, 5, 4, 6, 0]
排序后:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
以上是关于希尔排序笔记的主要内容,如果未能解决你的问题,请参考以下文章
python 学习笔记 -- 数据结构与算法 希尔排序 Shell Sort