首页 > 编程语言 >常见排序算法之希尔排序

常见排序算法之希尔排序

时间:2023-01-18 23:33:13浏览次数:40  
标签:arr insertIndex int 插入排序 算法 grap 希尔 排序


文章目录

  • ​​1、概述​​
  • ​​2、希尔排序之交换法​​
  • ​​3、希尔排序之移动法​​
  • ​​4、测试案例​​



1、概述

由于简单的插入排序每次数据量变多的时候,数据需要移动且交换数据的次数也会变多,继而影响效率。希尔排序就是在这个基础上进行改良,让数据能在较短的移动次数内就完成排序,继而提高排序效率。

希尔排序是希尔在1959年提出的一种排序算法。希尔排序也是一种插入排序,它是简单插入排序经过改进之后的一个更加高效的版本,也称为缩小增量排序(不断地除2)核心思想:把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止。

缩小增量的核心要领:

常见排序算法之希尔排序_System


希尔排序就是在之前的排序算法的基础上,进行了一个改良,它最本质的目的就是希望做出一些优化,使得我们的代码移动的次数减少。继而再配合我们的交换法(冒泡排序思想)和移动法(插入排序思想)。所以学习希尔排序就需要你对冒泡排序和插入排序已经熟练掌握,不然希尔排序对你来说就又是一个新的排序(本质我们只需要学会希尔排序的缩小增量思想就行)。



2、希尔排序之交换法

在缩小增量的基础上,配合冒泡排序的使用,该方法效率并不高

public class ShellSortTest01 {
public static void main(String[] args) {
int[] arr = {1, 123, 10, 3, 6, 34, 66, 23, 11, 71};
shellSort(arr);
System.out.println(Arrays.toString(arr));
}

public static void shellSort(int[] arr) {
int temp;

//1.每组的大小不断的减小为原来的一半,缩小增量的关键步骤
for (int grap = arr.length / 2; grap > 0; grap /= 2) {
//2.根据分出来的组数,遍历对应的每一组的其中一个元素,为下面的每一组数字的遍历开一头
for (int i = grap; i < arr.length; i++) {
//3.遍历每一组的数字,使用类似于冒泡的方式进行交换数据
for (int j = i - grap; j >= 0; j -= grap) {
if (arr[j] > arr[j + grap]) {
temp = arr[j + grap];
arr[j + grap] = arr[j];
arr[j] = temp;
}
}
}
}
}
}



3、希尔排序之移动法

在缩小增量的基础上,配合插入排序,效率较高

public class ShellSortTest02 {
public static void main(String[] args) {
int[] arr = {1, 123, 10, 3, 6, 34, 66, 23, 11, 71};
shellSort2(arr);
System.out.println(Arrays.toString(arr));
}

public static void shellSort2(int[] arr) {
int insertVale;
int insertIndex;

//1.每组的大小不断的减小为原来的一半
for (int grap = arr.length / 2; grap > 0; grap /= 2) {
//2.根据分出来的组数,遍历对应的每一组的其中一个元素,为下面的每一组数字的遍历开一头
for (int i = grap; i < arr.length; i++) {
//3.遍历每一组的数字,使用插入排序的方式进行排序
//其实内部就是一个插入排序,只是外面套了个缩小增量的壳
insertVale = arr[i];
insertIndex = i - 1;
while (insertIndex >= 0 && insertVale < arr[insertIndex]) {
arr[insertIndex + 1] = arr[insertIndex];
insertIndex--;
}
if (insertIndex + 1 != i) {
arr[insertIndex + 1] = insertVale;
}
}
}
}
}



4、测试案例

最终我们的测试案例,使用希尔排序配合移动法

public class ShellSortTest03 {
public static void main(String[] args) {
int[] arr = new int[80000];

for (int i = 0; i < 80000; i++) {
arr[i] = (int) (Math.random() * 80000);
}
long start = System.currentTimeMillis();
shellSort2(arr);
System.out.println(Arrays.toString(arr));
long end = System.currentTimeMillis();

System.out.println("shell排序花费的时间是:" + (end - start));

}

public static void shellSort2(int[] arr) {
//插入排序需要的变量
int insertVale;
int insertIndex;
for (int grap = arr.length / 2; grap > 0; grap /= 2) {
for (int i = grap; i < arr.length; i++) {
//原始的插入排序
insertVale = arr[i];
insertIndex = i - 1;
while (insertIndex >= 0 && insertVale < arr[insertIndex]) {
arr[insertIndex + 1] = arr[insertIndex];
insertIndex--;
}
if (insertIndex + 1 != i) {
arr[insertIndex + 1] = insertVale;
}
}
}
}
}

使用该方式的速率极快,这是在冒泡、选择、插入这三种中,最快的一种


标签:arr,insertIndex,int,插入排序,算法,grap,希尔,排序
From: https://blog.51cto.com/u_15942107/6019571

相关文章

  • m基于遗传优化算法的公式参数拟合matlab仿真
    1.算法描述遗传算法的原理        遗传算法GA把问题的解表示成“染色体”,在算法中也即是以二进制编码的串。并且,在执行遗传算法之前,给出一群“染色体”,也即是假......
  • 常见排序算法之选择排序
    文章目录​​1、概述​​​​2、代码实现​​​​3、测试代码​​1、概述选择排序(Selectionsort)是一种简单直观的排序算法。它的工作原理是:第一次从待排序的数据元素中选出......
  • 常见排序算法之冒泡排序
    文章目录​​1、概述​​​​2、传统代码​​​​3、优化后代码​​​​4、测试案例​​1、概述冒泡排序(BubbleSort),是一种的较简单且常见的的排序算法。它重复地访问排序的......
  • 常见排序算法之插入排序
    文章目录​​1、概述​​​​2、代码实现​​​​3、测试代码​​1、概述插入排序,一般也被称为直接插入排序。对于少量元素的排序,它是一个有效的算法。插入排序是一种最简......
  • 17种编程语言实现排序算法-冒泡排序
    开源地址https://gitee.com/lblbc/simple-works/tree/master/sort/bubbleSort1.安卓Java版privatevoidsort(int[]array){for(inti=0;i<array.length......
  • 司守奎《数学建模算法与应用》课后习题:线性规划
    写在最前面:    我是一个刚学数模的小白,觉得把自己的思路和代码啊公式写出来能提升学习效率,在参考了司守奎老师的《数学建模算法与应用》(第二版)一书后想把自己的想......
  • java-数组相关的算法(尚硅谷)
    1.数组元素的赋值(杨辉三角、回形数等)2.求数值型数组中元素的最大值、最小值、平均数、总和等3.数组的复制、反转、查找(线性查找、二分法查找)4.数组元素的排序算法一......
  • J Tokitsukaze and Sum of MxAb【2023牛客寒假算法基础集训营2】
    J TokitsukazeandSumofMxAb原题链接题意给出长为n的序列,对于所有的i,j求max\((|a_i-a_j|,|a_i+a_j|)\)之和思路对于两个负数\(a_i\)和\(a_j\),max\((|a_i-......
  • 刷算法题的一些Trick
    1字符串的输入在读字符串的时候,一般建议这么写charstr[N];//字符数组scanf("%s",str);//因为str可以当作指针,所以不用&puts(str);字符串作为函数参数的时候......
  • Graham算法笔记
    一切参照题解笔记部分:怎么判断旋转方向:如图,第一次入栈,P2直接进入此处为什么p3是左转:我们判断左转还是右转的方法:看要进入的点pi与栈顶的点pa和栈第二个点pb:此处就......