【数据结构实验】排序(二)希尔排序算法的详细介绍与性能分析
文章目录
- 1. 引言
- 2. 希尔排序算法原理
- 2.1 示例说明
- 2.2 时间复杂性分析
- 3. 实验内容
- 3.1 实验题目
- (一)输入要求
- (二)输出要求
- 3.2 算法实现
- 3.3 代码解析
- 3.4 实验结果
- 4. 实验结论
1. 引言
排序算法在计算机科学中扮演着至关重要的角色,对于数据的组织和搜索等任务有着深远的影响。希尔排序是一种插入排序的改进版本,通过引入增量的概念,能够在某些情况下显著提高排序的效率。
本文将详细介绍希尔排序算法的原理、实现,以及对其性能进行分析。
2. 希尔排序算法原理
希尔排序是一种基于插入排序的改进算法,由Donald L. Shell于1959年提出。其核心思想是将待排序的记录按下标的一定增量分组,对每组使用直接插入排序方法,随着增量逐渐减小,每组包含的记录越来越多,直至增量为1时,整个序列恰好被分成一个组,排序完成。
2.1 示例说明
考虑一个包含16个记录的输入文件,取渐减增量序列为 8 , 4 , 2 , 1 8, 4, 2, 1 8,4,2,1。初始时,将输入文件分成8个组:
- 组1: R 1 , R 9 R_1, R_9 R1,R9
- 组2: R 2 , R 10 R_2, R_{10} R2,R10
- 组3: R 3 , R 11 R_3, R_{11} R3,R11
- …
- 组8: R 8 , R 16 R_8, R_{16} R8,R16
对每个组使用直接插入排序算法进行排序。然后,取增量值为4,将文件分成4个组:
- 组1: R 1 , R 5 , R 9 , R 13 R_1, R_5, R_9, R_{13} R1,R5,R9,R13
- 组2: R 2 , R 6 , R 10 , R 14 R_2, R_6, R_{10}, R_{14} R2,R6,R10,R14
- 组3: R 3 , R 7 , R 11 , R 15 R_3, R_7, R_{11}, R_{15} R3,R7,R11,R15
- 组4: R 4 , R 8 , R 12 , R 16 R_4, R_8, R_{12}, R_{16} R4,R8,R12,R16
再次对每个组使用直接插入排序。重复这个过程,取增量值为2和1,最终完成整个排序。
2.2 时间复杂性分析
希尔排序的性能与所选取的分组长度序列密切相关。最坏情况下的时间复杂度为 O ( n 2 ) O(n^2) O(n2),但不同的分组长度序列会影响算法的实际性能。
- 当分组长度序列取 n 2 i \frac{n}{2^i} 2in时,最坏情况下时间复杂度为 O ( n 2 ) O(n^2) O(n2)。
- 实际应用中,取2.2作为递减因子效果更好。
- 当分组长度序列取形如 2 p 3 q 2^p3^q 2p3q且小于n的所有正整数的集合时,希尔排序的时间复杂度为 O ( n ⋅ ( log 2 n ) 2 ) O(n \cdot (\log_2 n)^2) O(n⋅(log2n)2)。
1969年,V. Pratt证明了以上结论。目前已知的最好分组长度序列是 { 1 , 4 , 10 , 23 , 57 , 132 , 301 , 701 , 1750 , . . . } \{1, 4, 10, 23, 57, 132, 301, 701, 1750, ... \} {1,4,10,23,57,132,301,701,1750,...},具有此分组序列的希尔排序比插入排序和堆排序要快。在小数组情况下比快速排序快,但对于大数组则可能比快速排序慢。此外,希尔排序是不稳定的排序算法。
3. 实验内容
3.1 实验题目
以{7,5,3,1}为渐减增量序列实现希尔排序算法 ShellSort.
(一)输入要求
第一组输入数据:
{27,32,33,21,57,96,64,87,14,43,15,62,99,11}
第二组输入数据:
{11,14,15,21,27,32,33,43,57,62,64,87,96,99}
第三组输入数据:
{99,96,87,64,62,57,43,33,32,27,21,15,14,11}
(二)输出要求
对每组输入数据,输出以下信息(要求必须要有关于输出数据的明确的提示信息):
- 输出整个排序过程总的关键词比较次数和总的记录移动次数;
- 每发生一次记录插入,输出整个文件一次;
- 输出增量为 7、5、3、1 时的关键词比较次数和记录移动次数
3.2 算法实现
#include <stdio.h>
#define n 14
void ShellSort(int R[n]){int r,i,j,k,Compare=0,Move=0;int d=7; //初始化增量值为7while(d>0){ //不断分组,并对各组排序int compare=0,move=0;for(i=d;i<n;i++){ //对各组做直接插入排序r=R[i];j=i;while(j>d-1&&R[j-d]>r){compare++;R[j]=R[j-d];j-=d;}if(j!=i){move++;R[j]=r;for(k=0;k<n;k++){printf("%d ", R[k]);}printf("\n");} }printf("\n增量值为%d时的关键词比较次数是%d,记录移动次数是%d\n\n",d,compare,move);d=d-2; //计算新的增量值,{7,5,3,1}Compare+=compare;Move+=move;}printf("关键词的总比较次数是%d,总的记录移动次数是%d\n",Compare,Move);
}
int main(){int i;//int R[n]={27,32,33,21,57,96,64,87,14,43,15,62,99,11};int R[n]={11,14,15,21,27,32,33,43,57,62,64,87,96,99};//int R[n]={99,96,87,64,62,57,43,33,32,27,21,15,14,11};ShellSort(R);printf("最后结果:");for(i=0;i<n;i++){printf("%d ",R[i]);}
}
3.3 代码解析
- 宏定义
#define n 14
定义宏 n
,表示数组的长度为14,在后续代码中可以方便地使用 n
来表示数组的长度,而不需要硬编码。
-
希尔排序函数
参数是一个整型数组R
,表示待排序的数组。在函数内部,通过不断缩小增量的方式,对数据进行插入排序。具体来说,在每一轮循环结束后,更新增量的值,采用一定的方式递减。这里选择减小2的增量序列{7, 5, 3, 1}
。int d = 7; while (d > 0) {// ...d=d-2; //计算新的增量值,{7,5,3,1}// ... }
使用
while
循环,不断缩小增量d
,并在每一轮循环中进行插入排序。增量的选择是关键,这里初始设置为7,然后逐渐减小。for (i = d; i < n; i++) { // ... }
针对每个分组,从第
d
个元素开始,进行插入排序。while (j > d - 1 && R[j - d] > r) { // ... }
在插入排序的过程中,通过比较和移动元素,确保分组内的元素是有序的。
-
输出结果
printf("\n增量值为%d时的关键词比较次数是%d,记录移动次数是%d\n\n", d, compare, move);
在每一轮排序结束后,输出该轮排序的比较次数和记录移动次数,从而了解算法在不同步长下的性能。
printf("关键词的总比较次数是%d,总的记录移动次数是%d\n", Compare, Move);
在整个排序完成后,输出总的比较次数和记录移动次数,提供了算法整体性能的信息。
- 主函数
int main(){int i;// int R[n]={27,32,33,21,57,96,64,87,14,43,15,62,99,11};// int R[n]={11,14,15,21,27,32,33,43,57,62,64,87,96,99};int R[n]={99,96,87,64,62,57,43,33,32,27,21,15,14,11};ShellSort(R);printf("最后结果:");for(i=0;i<n;i++){printf("%d ",R[i]);}
}
创建一个包含14个元素的数组 R
,并调用 ShellSort
函数对其进行排序。最后输出排序后的数组。
3.4 实验结果
4. 实验结论
希尔排序是一种高效的排序算法,通过引入增量的方式,能够在某些情况下显著提高插入排序的性能。选择合适的分组长度序列对算法的实际效果有重要影响,而已知的最佳序列 { 1 , 4 , 10 , 23 , 57 , 132 , 301 , 701 , 1750 , . . . } \{1, 4, 10, 23, 57, 132, 301, 701, 1750, ... \} {1,4,10,23,57,132,301,701,1750,...}在实践中表现优异。
需要注意的是,希尔排序是不稳定的排序算法。在实际应用中,根据数据规模和特性选择不同的排序算法是很重要的,希尔排序在一些场景下可能比其他排序算法更适用。希尔排序的性能对于分组长度序列的选择非常敏感,因此在实际使用中需要根据具体情况进行调优。
相关文章:

【数据结构实验】排序(二)希尔排序算法的详细介绍与性能分析
文章目录 1. 引言2. 希尔排序算法原理2.1 示例说明2.2 时间复杂性分析 3. 实验内容3.1 实验题目(一)输入要求(二)输出要求 3.2 算法实现3.3 代码解析3.4 实验结果 4. 实验结论 1. 引言 排序算法在计算机科学中扮演着至关重要的角色…...

微信小程序开发者工具] ? Enable IDE Service (y/N) ESC[27DESC[27C
在HBuilder运行微信小程序开发者工具报错 如何解决 打开微信小程序开发者工具打开设置--->安全设置--->服务器端口选择打开就可以啦...
【数据结构】E : 货币套汇(图路径)
E : 货币套汇(图路径) Description 套汇是指利用货币汇兑率的差异将一个单位的某种货币转换为大于一个单位的同种货币。例如,假定1 美元可以买0.7 英镑,1 英镑可以买9.5 法郎,1法郎可以买到0.16美元。通过货币兑换&a…...
图书管理系统源码,图书管理系统开发,图书借阅系统源码SqlHelper数据库访问操作方法简述
SqlHelper 是封装了数据库操作方法的类库,使用它我们可以链接数据库操作数据库表数据增删改查,其中主要SqlConnection ,ExecuteNonQuery,ExecuteScalar,ExecuteDataTable四个主要方法SqlConnection负责根据访问配置文件web.config中connstr链接数据库字符串去打开数据库,…...
富文本编辑器的实现与回显
文本编辑器实现-wangeditor 写之前记得安装wangeditor插件,到时候报错别赖我 import “wangeditor/editor/dist/css/style.css”; import { Editor, Toolbar } from “wangeditor/editor-for-vue”; defineOptions({name: "BaseEditor" });const mode …...

探索亚马逊云科技云存储服务的性能
文章作者:Libai 引言 随着企业越来越多地依赖云存储解决方案,确保存储性能的最佳状态变得至关重要。在本文中,我们将探讨在亚马逊云科技云存储服务上进行存储性能基准测试的重要性,以及如何帮助企业做出资源分配和优化的明智决策…...

初出茅庐的小李博客之C语言必备知识共用体
C语言必备知识共用体 共用体是一种构造数据类型,有时候也称之为联合体。 它的用途: 使几个不同类型的变量共占一段内存。 共用体举例 union 共用体名 { 类型标识符 成员名;类型标识符 成员名; };union data //共用体名字是data{ int i; …...

vue3+elementPlus之侧边菜单栏功能
选择默认的颜色,将代码拷贝至<el-aside>模块中 稍微把不需要的修改一下。 <template><div class"common-layout"><el-container><el-header class"homeHeader"><div class"headerTitle">Devops…...

阿里云服务器安装mysql数据库之后无法远程连接
目录 一、mysql安装完成后直接远程远程连接阿里云服务器上的MySQL会报下述错误: 1、修改root用户的host 为% 登录MySQL 后 执行 2、修改完成后执行 3、退出mysql 重启mysql服务 exit; 4、修改完成后需要设置阿里云的安全规则。 二、dbaver测试链…...

如何把自己银行卡里的钱转账充值到自己支付宝上?
原文来源:https://www.caochai.com/article-4524.html 支付宝余额是支付宝核心功能之一,主要用于网购支付、线下支付、转账等场景。用户可以将银行卡、余额宝等资金转入或转出至支付宝余额,实现快速转账和支付。 如何把自己银行卡里的钱转账…...

Flink Flink中的分流
一、什么是分流 所谓“分流”,就是将一条数据流拆分成完全独立的两条、甚至多条流。也就是基于一个DataStream,定义一些筛选条件,将符合条件的数据拣选出来放到对应的流里。 二、基于filter算子的简单实现分流 其实根据条件筛选数据的需求…...

传输层协议[精选]
网络: 跨主机通信. 互联网通信: 两点之间的通信路径有无数条. 集线器: 把一根网线差出来两根,但是同一时刻只能有一根线跑.交换机: 组建局域网.路由器: 本质就是将两个局域网连接起来 交换机和路由器之间的区别越来越模糊. 调制解调器: 使用电话线上网的时候,需要将电话线的模…...
LeetCode算法题解|474. 一和零
474. 一和零 题目链接:474. 一和零 题目描述 给你一个二进制字符串数组 strs 和两个整数 m 和 n 。 请你找出并返回 strs 的最大子集的长度,该子集中 最多 有 m 个 0 和 n 个 1 。 如果 x 的所有元素也是 y 的元素,集合 x 是集合 y 的 子…...

一种太阳能风能市电互补路灯方案介绍
太阳能市电互补路灯是一种环保、节能的照明设施,它利用太阳能进行发电并实现照明。这种路灯在白天吸收阳光并将其转化为电能,到了晚上则利用储存的电能为LED灯提供电力,实现照明功能。下面叁仟智慧将详细介绍太阳能市电互补路灯灯的工作原理和…...

世微 dc-dc降压恒流 LED汽车大灯 单灯 14V5A 68W车灯驱动方案 AP5191
产品描述 AP5191是一款PWM工作模式,高效率、外围简单、外置功率MOS管,适用于4.5-150V输入的高精度降压LED恒流驱动芯片。输出最大功率150W,最大电流6A。AP5191可实现线性调光和PWM调光,线性调光脚有效电压范围0.55-2.6V.AP5191 工作频率可以…...

基于时隙的多重冗余流指纹模型
文章信息 论文题目:基于时隙的多重冗余流指纹模型 期刊(会议):网络与信息安全学报 时间:2023 级别:CCF C 概述 为确保内生网络流量安全可信,本文在研究流水印及其扩展的流指纹机制的基础上&a…...

Visual Studio 2019 C# System.BadImageFormatException 解决方法
文章目录 1.DLL文件缺失或不匹配原因解决方法 2.系统环境变量Path下内容过多原因解决方法 3.位数错误原因解决方法 分析几种可能因素 1.DLL文件缺失或不匹配 原因 检查对应Debug路径下的DLL文件是否有缺失 解决方法 将对应的DLL文件放到Debug文件夹里面,检查冗余…...

深度学习之基于YoloV5车辆和行人目标检测系统
欢迎大家点赞、收藏、关注、评论啦 ,由于篇幅有限,只展示了部分核心代码。 文章目录 一项目简介YOLOv5 简介YOLOv5 特点 车辆和行人目标检测系统 二、功能三、系统四. 总结 一项目简介 # 深度学习之基于 YOLOv5 车辆和行人目标检测系统介绍 深度学习在…...

Django框架之中间件
目录 一、引入 二、Django中间件介绍 【1】什么是Django中间件 【2】Django中间件的作用 【3】示例 三、Django请求生命周期流程图 四、Django中间件是Django的门户 五、Django中间件详解 六、中间件必须要掌握的两个方法 (1) process_request (2) process_respon…...

BTC 复兴:Ordinals 带来创新活力,BitVM 与 BitStream 相继问世
除了备受瞩目的 ETF,今年 Bitcoin 生态迎来全新的发展活力和机遇。Ordinals 协议的横空出世,以此为基础诞生的 BRC20 协议给整个比特币生态带去了一波新的能量,迎来铭文热度高涨。而诸如 BitVM、BitStream 等新技术甫一问世,便引发…...
Java 语言特性(面试系列2)
一、SQL 基础 1. 复杂查询 (1)连接查询(JOIN) 内连接(INNER JOIN):返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...

阿里云ACP云计算备考笔记 (5)——弹性伸缩
目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...

高等数学(下)题型笔记(八)空间解析几何与向量代数
目录 0 前言 1 向量的点乘 1.1 基本公式 1.2 例题 2 向量的叉乘 2.1 基础知识 2.2 例题 3 空间平面方程 3.1 基础知识 3.2 例题 4 空间直线方程 4.1 基础知识 4.2 例题 5 旋转曲面及其方程 5.1 基础知识 5.2 例题 6 空间曲面的法线与切平面 6.1 基础知识 6.2…...
第25节 Node.js 断言测试
Node.js的assert模块主要用于编写程序的单元测试时使用,通过断言可以提早发现和排查出错误。 稳定性: 5 - 锁定 这个模块可用于应用的单元测试,通过 require(assert) 可以使用这个模块。 assert.fail(actual, expected, message, operator) 使用参数…...
Spring Boot面试题精选汇总
🤟致敬读者 🟩感谢阅读🟦笑口常开🟪生日快乐⬛早点睡觉 📘博主相关 🟧博主信息🟨博客首页🟫专栏推荐🟥活动信息 文章目录 Spring Boot面试题精选汇总⚙️ **一、核心概…...
【python异步多线程】异步多线程爬虫代码示例
claude生成的python多线程、异步代码示例,模拟20个网页的爬取,每个网页假设要0.5-2秒完成。 代码 Python多线程爬虫教程 核心概念 多线程:允许程序同时执行多个任务,提高IO密集型任务(如网络请求)的效率…...
【Go语言基础【12】】指针:声明、取地址、解引用
文章目录 零、概述:指针 vs. 引用(类比其他语言)一、指针基础概念二、指针声明与初始化三、指针操作符1. &:取地址(拿到内存地址)2. *:解引用(拿到值) 四、空指针&am…...

如何更改默认 Crontab 编辑器 ?
在 Linux 领域中,crontab 是您可能经常遇到的一个术语。这个实用程序在类 unix 操作系统上可用,用于调度在预定义时间和间隔自动执行的任务。这对管理员和高级用户非常有益,允许他们自动执行各种系统任务。 编辑 Crontab 文件通常使用文本编…...

[ACTF2020 新生赛]Include 1(php://filter伪协议)
题目 做法 启动靶机,点进去 点进去 查看URL,有 ?fileflag.php说明存在文件包含,原理是php://filter 协议 当它与包含函数结合时,php://filter流会被当作php文件执行。 用php://filter加编码,能让PHP把文件内容…...

Ubuntu Cursor升级成v1.0
0. 当前版本低 使用当前 Cursor v0.50时 GitHub Copilot Chat 打不开,快捷键也不好用,当看到 Cursor 升级后,还是蛮高兴的 1. 下载 Cursor 下载地址:https://www.cursor.com/cn/downloads 点击下载 Linux (x64) ,…...