ds排序--希尔排序_图解直接插入排序和希尔排序

前言

这次我们介绍插入类排序中的 直接插入排序希尔排序

对于直接插入排序,虽然它的时间复杂度也是 O(n^2) ,但是在元素 有序或近乎有序 的情况下,时间复杂度可以降为 O(n) ,效率比 O(nlogn) 的算法还要高。

然而对于大规模的乱序数组,使用直接插入排序的效率是非常低的。此时我们需要使用希尔排序,希尔排序在直接插入排序的基础上,弥补了直接插入排序只能比较相邻元素的不足,使得可以按照指定步长比较元素,充分发挥了直接插入排序对于小规模有序数组排序的优势。

下面我们分别介绍 直接插入排序希尔排序 两类插入排序。

直接插入排序

有如下数组,我们需要对它从小到大排序,利用直接插入排序步骤如下:

566e0d3475bc2821d21cd038ba92e2ad.png
  1. 将第二个元素和第一个元素比较,小于第一个元素的话交换位置,这样第二个元素作为最小的元素排在了最前面,大于的话不交换。
  2. 然后将第三个元素和第二个元素比较,小于第二个元素的话交换位置,然后再和第一个元素比较,小于第一个元素的话再次交换位置,这样第三个元素作为最小的元素排在了最前面,大于的话不交换。
  3. 以此类推,直到最后一个元素插入到合适位置。

下图展示了整个排序的过程:

71e7de16283e8f4e4393cbcac92be08e.png

直接插入排序的代码:

public static void sort(Comparable[] arr) {    int n = arr.length;    // 0位置不需要比,从1到最后一个位置n-1    for (int i = 1; i <= n - 1; i++) {        for( int j = i; j > 0 && arr[j].compareTo(arr[j-1]) < 0 ; j--) {            swap(arr, j, j-1);        }    }}private static void swap(Object[] arr, int i, int j) {    Object t = arr[i];    arr[i] = arr[j];    arr[j] = t;}

优化

优化的思路就是将内循环中每次 swap 交换操作修改为 让较大的元素后移,最后再进行一次交换 ,这样一来访问数组的次数就减少了(交换需要三行,赋值只需要一行)。

优化步骤如下:

  1. 每次先保存当前插入的元素。
  2. 将当前保存的元素(第二个元素)和第一个元素比较,小于第一个元素的话,将第一个元素移动到第二个元素位置,然后当前保存的元素移动到第一个元素位置,这样第二个元素作为最小的元素排在了最前面。
  3. 将当前保存的元素(第三个元素)和第二个元素比较,小于第二个元素的话,将第二个元素移动到第三个元素位置,然后当前保存的元素移动到第二个元素位置,接着小于第一个元素的话再次执行以上操作,这样第三个元素作为最小的元素排在了最前面。
  4. 以此类推,直到最后一个元素插入到合适位置。

下图展示了优化思路的过程:

357085a0c534ca38c69bb3e4c6621555.png

优化的直接插入排序代码:

public static void sort(Comparable[] arr) {    int n = arr.length;    // 0位置不需要比,从1到最后一个位置n-1    for (int i = 1; i <= n - 1; i++) {        // 保存当前插入的元素        Comparable e = arr[i];        int j;        for (j = i; j > 0 && arr[j - 1].compareTo(e) > 0; j--) {            arr[j] = arr[j - 1];        }        arr[j] = e;    }}

希尔排序

上面我们介绍了直接插入排序,它对于大规模乱序数组的排序效率比较低,因为只能交换相邻的元素,所以元素只能一点一点地从数组的一端移动到另一端。此外,如果最小的元素在数组的末尾,那么将它插入到正确位置需要移动 N-1 次。

希尔排序的出现,解决了上述问题。它能够交换不相邻的元素以对数组的局部进行排序,并最终用直接插入排序将局部有序的数组排序。

希尔排序的思想是使数组中任意间隔为 h 的元素都是有序的。这样的数组也叫作 h 有序数组 。我们不研究 h 是如何得来的,这里直接使用了《算法》书中的 h 步长序列。

h = 3*h+1 ,根据 h 的取值分别为1、4、13 ...

实际上只需要把直接插入排序代码中移动元素的距离由 1 改为 h 即可。这样,希尔排序就转换为了一个类似于直接插入排序但使用不同增量的过程。

下图展示了希尔排序的过程:

8428de2e145e53ff8a82c583e09d5a50.png

如果你仔细观察,会发现在 h=1 时,相比直接插入排序,比较的次数大大减少了,这是因为希尔排序使得部分子数组有序,而直接插入排序对于近乎有序的数组,效率是非常高的。

希尔排序代码:

public static void sort(Comparable[] arr) {    int n = arr.length;    // 步长序列: 1, 4, 13...    int h = 1;    while (h < n / 3) {        h = 3 * h + 1;    }    while (h >= 1) {        for (int i = h; i < n; i++) {            // 将 arr[i] 插入到 arr[i-h], arr[i-2*h], arr[i-3*h]... 中            Comparable e = arr[i];            int j;            // 优化的插入排序            for (j = i; j >= h && e.compareTo(arr[j - h]) < 0; j -= h) {                arr[j] = arr[j - h];            }            arr[j] = e;        }        h /= 3;    }}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/346793.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

jsf 配置_JSF Tomcat配置示例

jsf 配置JavaServer Faces (JSF)是一个Web应用程序框架&#xff0c;旨在简化基于Web的用户界面的开发集成。 它用于开发和构建服务器端用户界面组件&#xff0c;并在Web应用程序中使用它们。 JSF技术基于Model-View-Controller (MVC)架构&#xff0c;并且通过在页面中使用可重用…

tomcat8日志乱码_Tomcat输出日志乱码解决

请先检查一下是不是由于log4J没有指定编码方式所导致的.log4j.appender.File org.apache.log4j.DailyRollingFileAppender#重点是看一下有没有这个,如果没有则加上.#加上之后需要将之前的日志文件删除,否则有可能不会重新写入日志.log4j.appender.File.Encoding UTF-8log4j.a…

使用Datastax Java驱动程序与Cassandra进行交互

今天&#xff0c;我这次返回了更多的Cassandra和Java集成&#xff0c;重点是使用Datastax Java驱动程序&#xff0c;而不是我已经写了很多文章的Spring Data Cassandra。 Spring Data实际上使用了Datastax驱动程序来与Cassandra进行交互&#xff0c;但是在其之上还附带了一些额…

java forkjoin MySQL_Java并发fork-join框架

fork-join框架允许在几个工作进程中断某个任务&#xff0c;然后等待结果组合它们。 它在很大程度上利用了多处理器机器的生产能力。 以下是fork-join框架中使用的核心概念和对象。ForkFork是一个进程&#xff0c;其中任务将其分成可以并发执行的较小且独立的子任务。语法Sum le…

无法加载可扩展计数器_多核可扩展计数器

无法加载可扩展计数器到处都需要计数器&#xff0c;例如&#xff0c;查找应用程序的关键KPI&#xff0c;应用程序的负载&#xff0c;服务的请求总数&#xff0c;用于查找应用程序吞吐量的一些KPI等。 由于所有这些需求&#xff0c;并发复杂性也增加了&#xff0c;这使这个问题…

linux忘记mysql密码_linux下忘记mysql root密码解决办法 | 系统运维

引言&#xff1a;在linux系统中&#xff0c;如果忘记了MySQL的root密码&#xff0c;有没有办法重新设置新密码呢&#xff1f;答案是肯定的&#xff0c;下面教大家一个比较简单的重置MySQL root密码的办法&#xff1a;1、编辑MySQL配置文件my.cnf系统运维www.osyunwei.com温馨提…

Java 10中的本地类型推断,或者如果它像鸭子一样嘎嘎叫

最近&#xff0c;Oracle采用了一种新策略&#xff0c;即每六个月发布一次新的语言版本。 该策略假定只有每个第3版都将提供长期支持或LTS。 快速说明&#xff1a; 具有LTS的当前版本是Java 8&#xff1b; Java 9仅应在2018年3月之前获得支持&#xff0c;因此已经结束。 Java…

mysql从dos界面_从DOS界面进入MYSQL数据库

新手学习数据库&#xff0c;从比较简单的mysql开始。从DOS界面进入mysql数据库其实跟配置java环境变量一样&#xff0c;要先设置环境变量(右击我的电脑-属性-高级-环境变量)。找到mysql的安装位置&#xff0c;把安装目录下“...mysql\bin\"这个地址放到环境变量Path值中&a…

更快地重复访问Java的Java类名?

Claes Redestad在core-libs-dev邮件列表上发布了消息“ RRF&#xff1a;8187123 &#xff1a;&#xff08;反映&#xff09;Class&#xff03;getCanonicalName和Class&#xff03;getSimpleName是性能问题的一部分 ”&#xff0c;他在邮件列表中要求审查建议的更改“以启用缓存…

mysql中cast函数_mysql中cast函数的使用 用于强制类型转换 (转载)

例子&#xff1a;SELECTstr_to_date(concat(year(a.tb_time),date_format(a.tb_time,%m),01),%Y%m%d) tb_time,cast(a.category_id as char) category_id,a.category_name,sum(a.tendered_sum)/sum(a.winbid) tendered_sum,sum(a.winbid_sum)/sum(a.winbid) winbid_avgfrom( SE…

dht11温湿度传感器_Arduino不调用库实现DHT11数据读取

DHT11概述DHT11数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器&#xff0c;它应用专用的数字模块采集技术和温湿度传感技术&#xff0c;确保产品具有极高的可靠性和卓越的长期稳定性。传感器包括一个电阻式感湿元件和一个NTC测温元件&#xff0c;并与一个高性…

rete_RIP RETE时间来获得PHREAKY

rete我刚刚完成了有关新规则算法PHREAK的高级文档&#xff0c;PHREAK是混合推理中的一个文字游戏。 它仍然有点粗糙和高水平&#xff0c;但希望仍然很有趣。 它建立在ReteOO之上&#xff0c;非常好阅读。 ReteOO算法 ReteOO是在3、4和5系列发行版中开发的。 它采用了RETE算法并…

mysql 存储过程 插入记录_mysql 存储过程 插入记录

{"moduleinfo":{"card_count":[{"count_phone":1,"count":1}],"search_count":[{"count_phone":4,"count":4}]},"card":[{"des":"阿里云数据库专家保驾护航&#xff0c;为用户…

Java技巧:创建监视友好的ExecutorService

在本文中&#xff0c;我们将扩展具有监视功能的ExecutorService实现。 这种监视功能将帮助我们在实时生产环境中测量多个池参数&#xff0c;即活动线程&#xff0c;工作队列大小等。 它还将使我们能够衡量任务执行时间&#xff0c;成功任务计数和失败任务计数。 监控库 至于监…

java如果把字符串转成对象_Java中的重复对象:不仅仅是字符串

当Java应用程序消耗大量内存时&#xff0c;它本身就会出现问题&#xff0c;并可能导致GC压力增加和GC暂停时间过长。在我之前的一篇文章中&#xff0c;我讨论了Java中常见的内存浪费源&#xff1a;重复字符串。两个 java.lang.String 对象&#xff0c; a 并 b 在重复时 a ! b &…

mysql五大子句_MySQL的查询语句中可以使用以下哪个子句来表示分组查询

【多选题】人类行为遗传学工作者倾向于把人的行为遗传分为哪几类【填空题】MySQL的连接操作包括内连接、( )和交叉连接。【判断题】社会生活类尤其是人文风光类纪录片的解说则多用文学、 散文手法, 既抒情又有解释说明, 语言华丽富于美感,情感真挚浓郁。【单选题】1 、作业区边…

批处理 设置电脑最佳性能_批处理最佳做法

批处理 设置电脑最佳性能大多数应用程序至少具有一个批处理任务&#xff0c;在后台执行特定的逻辑。 编写批处理作业并不复杂&#xff0c;但是您需要了解一些基本规则&#xff0c;我将列举一些我发现最重要的规则。 从输入类型的角度来看&#xff0c;处理项目可以通过轮询处理…

layui登录页面写入数据_layui基本使用(动态获取数据,并把需要的数据传到新打开的窗口)...

\n‘ ‘ \n‘ ‘ \n‘ ‘ \n‘ ‘ \n‘ ‘ \n‘ ‘ \n‘ ‘ ‘ item.TITLE ‘\n‘ ‘ ‘ item.ZDRQ ‘\n‘ ‘ \n‘ ‘ \n‘ ‘ \n‘ ‘ \n‘ ‘ ‘ item.CDATE ‘\n‘ ‘ ‘ item.TJR ‘\n‘ ‘ \n‘ ‘ \n‘ ‘ ‘‘//消息的跳转页面$(".xiaoxi").click(fu…

mysql 5.6自动任务_mysql定时执行某任务

查看event是否开启: show variables like %sche%;将事件计划开启: set global event_scheduler1;关闭事件任务: alter event e_test ON COMPLETION PRESERVE DISABLE;开户事件任务: alter event e_test ON COMPLETION PRESERVE ENABLE;简单实例.创建表 CREATE TABLE test(endti…

JVM体系结构:JVM类加载器和运行时数据区

各位读者好&#xff01; 在JVM系列的上一篇文章中&#xff0c;开发人员了解了Java虚拟机&#xff08;JVM&#xff09;及其体系结构。 本教程将帮助开发人员正确回答以下主题的问题&#xff1a; ClassLoader子系统 运行时数据区 1.简介 在继续之前&#xff0c;让我们看一下Ja…