图解Java排序算法之希尔排序

yizhihongxing

图解Java排序算法之希尔排序:完整攻略

什么是希尔排序

希尔排序(Shell Sort),又称递减增量排序法,是插入排序的一种更高效的改进版本。希尔排序是将整个序列分成若干子序列,对于每个子序列进行直接插入排序,减小增量再次排序,循环直至增量为1。

希尔排序的原始实现

首先看一下希尔排序的原始实现(不采用递归实现):

public static void shellSort(int[] arr) {
    int n = arr.length;
    for (int gap = n / 2; gap > 0; gap /= 2) {
        for (int i = gap; i < n; i++) {
            for (int j = i; j >= gap && arr[j - gap] > arr[j]; j -= gap) {
                // 交换位置
                int temp = arr[j];
                arr[j] = arr[j - gap];
                arr[j - gap] = temp;
            }
         }
    }
}

希尔排序的优化实现

1. Knuth序列增量

希尔本人给出的增量序列为:d1=n/2, di=di-1/2 。但实际上这个增量序列并不是最优的,Knuth提出了一种增量序列:d1=1,di=3*di-1+1 。这个增量序列可以取到 O(n^1.25) 的时间复杂度。

我们可以将原始实现中的for循环修改一下即可:

public static void shellSort(int[] arr) {
    int n = arr.length;
    int gap = 1;
    while (gap < n / 3) {
        gap = gap * 3 + 1;
    }
    for (; gap > 0; gap /= 3) {
        for (int i = gap; i < n; i++) {
            for (int j = i; j >= gap && arr[j - gap] > arr[j]; j -= gap) {
                // 交换位置
                int temp = arr[j];
                arr[j] = arr[j - gap];
                arr[j - gap] = temp;
            }
         }
    }
}

2. 使用插入排序

希尔排序可以看作是插入排序的一种优化版,我们可以在内层循环中使用插入排序,并且使用直接插入排序的优化,这样可以进一步提升排序效率。示例代码如下:

public static void shellSort(int[] arr) {
    int n = arr.length;
    int gap = 1;
    while (gap < n / 3) {
        gap = gap * 3 + 1;
    }
    for (; gap > 0; gap /= 3) {
        for (int i = gap; i < n; i++) {
            int temp = arr[i];
            int j = i - gap;
            while (j >= 0 && arr[j] > temp) {
                arr[j + gap] = arr[j];
                j -= gap;
            }
            arr[j + gap] = temp;
        }
    }
}

示例说明

示例1

假设有一个数组arr,其值为{3, 7, 2, 1, 9, 5, 8, 4}。我们对其进行希尔排序,使用增量序列d1=1, di=3*di-1+1。

  1. gap=4,将整个序列分成了4组:3 9、7 5、2 8、1 4,对每一组进行插入排序,得到{3, 5, 2, 1, 9, 7, 8, 4};
  2. gap=1,将整个序列分成了1组:3 5 2 1 9 7 8 4,对整个序列进行插入排序,得到{1, 2, 3, 4, 5, 7, 8, 9}。

最终的排序结果为{1, 2, 3, 4, 5, 7, 8, 9}。

示例2

假设有一个数组arr,其值为{9, 1, 5, 8, 3, 7, 4, 6, 2}。我们对其进行希尔排序,使用增量序列d1=4,d2=2,d3=1。

  1. gap=4,将整个序列分成了两组:9 3 4 2 与 1 5 7 6 8,对每一组进行插入排序,得到{2, 3, 4, 6, 1, 5, 7, 9, 8};
  2. gap=2,将整个序列分成了两组:2 4 1 7 8 与 3 6 5 9,对每一组进行插入排序,得到{1, 2, 4, 5, 3, 6, 7, 9, 8};
  3. gap=1,整个序列为{1, 2, 4, 5, 3, 6, 7, 9, 8},对其进行插入排序,得到{1, 2, 3, 4, 5, 6, 7, 8, 9}。

最终的排序结果为{1, 2, 3, 4, 5, 6, 7, 8, 9}。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:图解Java排序算法之希尔排序 - Python技术站

(0)
上一篇 2023年5月26日
下一篇 2023年5月26日

相关文章

  • 浅谈Java中ThreadLocal内存泄露的原因及处理方式

    浅谈Java中ThreadLocal内存泄露的原因及处理方式 1. ThreadLocal的原理 ThreadLocal是Java中提供的一种线程局部变量。它为每个线程都提供了自己的局部变量,并且在线程内部是完全独立的。可以把ThreadLocal对象看作是一个map,key是线程,value是线程对应的变量值。当多个线程都使用同一个ThreadLocal对…

    Java 2023年5月20日
    00
  • Java8方法引用和构造引用代码实例

    针对“Java8方法引用和构造引用代码实例”的完整攻略,我这里给出了以下步骤: 1. 概念介绍 首先需要了解方法引用和构造引用的概念。方法引用就是引用一个已经存在的函数,而不是像Lambda表达式那样提供一个匿名函数实现。其中有三种主要的引用类型: 静态方法引用:引用静态函数。 实例方法引用:引用实例方法。 构造方法引用:引用类的构造方法。 构造引用与方法引…

    Java 2023年5月30日
    00
  • Java高级架构之FastDFS分布式文件集群详解

    Java高级架构之FastDFS分布式文件集群详解 FastDFS是一个开源的高性能分布式文件系统,可伸缩的分布式文件存储系统,是以跨平台、高效、高可靠性为特点的分布式文件系统,并以其优异性能成为国内外互联网公司分布式文件存储的不二之选。 概述 FastDFS是一个由跟踪服务器、存储服务器组成的分布式文件系统。跟踪服务器负责调度存储服务器,存储服务器则负责文…

    Java 2023年5月19日
    00
  • 常见的几种web攻击的防范办法 web常见攻击方式

    下面就为你讲解一下常见的几种Web攻击的防范办法。 常见的Web攻击方式 以下是Web常见攻击方式: XSS攻击 CSRF攻击 SQL注入攻击 1. XSS攻击 定义 XSS攻击即跨站脚本攻击,攻击者在网页中嵌入恶意脚本,当用户访问该页面时,该恶意脚本就可以获取用户的cookie等信息,从而获取用户的敏感信息。 防范办法 对用户输入的内容进行过滤和转义,尤其…

    Java 2023年5月20日
    00
  • Java基础之Bean的创建、定位和使用

    Java基础之Bean的创建、定位和使用 在Java开发中,Bean是非常常用的一种Java类。Bean是一种被特殊编写的Java类,通常用于封装和传输数据,它拥有以下几个特点: 具有无参构造器 具有getter/setter方法 实现序列化接口 下面我们将对Bean的创建、定位和使用进行详细讲解。 Bean的创建 JavaBean的创建需要满足上述特点,以…

    Java 2023年5月26日
    00
  • Zend Studio (eclipse)使用速度优化方法

    Zend Studio (Eclipse)使用速度优化方法 Zend Studio是一个在Eclipse基础上扩展的PHP IDE,提供了众多的功能,但是在使用中可能会出现卡顿、启动慢等问题。本文将给出一些常见的优化方法,以提高Zend Studio的使用效率。 1. 调整启动参数 默认情况下,Zend Studio会使用JVM的默认设置进行启动,这可能会导…

    Java 2023年6月15日
    00
  • IDEA创建SpringBoot父子Module项目的实现

    下面是”IDEA创建SpringBoot父子Module项目的实现”完整攻略,以及两个示例。 一、什么是SpringBoot SpringBoot是基于Spring框架的一个快速开发脚手架,它简化了Spring应用的配置过程,提供了各种组件的自动化配置,在不需要过多配置的情况下,能够轻松地搭建一个基于Spring的Web应用程序。 二、什么是父子Module…

    Java 2023年5月19日
    00
  • Spring AOP定义Before增加实战案例详解

    在Spring应用程序中,我们可以使用AOP(面向切面编程)来实现横切关注点的模块化。在本文中,我们将详细介绍如何使用Spring AOP定义Before增强,并提供两个示例说明。 1. Before增强 Before增强是AOP中的一种通知类型,它在目标方法执行之前执行。我们可以使用@Before注解将一个方法标记为Before增强。下面是一个示例代码: …

    Java 2023年5月18日
    00
合作推广
合作推广
分享本页
返回顶部