【数据结构】插入排序:直接插入排序、折半插入排序、希尔排序的学习知识总结

目录

1、排序的基本概念

2、直接插入排序

2.1 算法思想 

2.2 代码实现 

3、折半插入排序

3.1 算法思想

3.2 代码实现 

4、希尔排序

4.1 算法思想

4..2 代码实现 


1、排序的基本概念

排序是将一组数据按照预定的顺序排列的过程,排序的基本概念包括以下内容:

  1. 关键字:排序时按照哪个字段进行排序,该字段称为关键字。

  2. 排序规则:排序时按照升序或降序的方式排列。升序表示从小到大排列,降序表示从大到小排列。

  3. 稳定性:排序算法如果经过排序后,具有相同关键字的元素,排序前后的相对顺序是否保持不变。如果保持不变,该排序算法就是稳定的。

  4. 时间复杂度:排序算法进行排序所需要的时间复杂度。

  5. 空间复杂度:排序算法进行排序所需要的额外空间复杂度,即算法需要占用的额外内存大小。

2、直接插入排序

2.1 算法思想 

        直接插入排序算法的思想是将待排序的元素插入到已经排好序的元素序列中,从而得到一个新的、更大的有序序列。

        具体来说,算法从第二个元素开始遍历待排序序列,将当前元素插入到已经排好的元素序列中的正确位置上,使得插入后仍然保持有序。因为初始时已经有一个元素的有序序列,所以排序过程中每次插入的元素都将比已经排好序的元素序列中的元素小,因此不会影响已经排好序的元素序列的有序性。当遍历完整个序列,待排序序列就被完全插入到已经排好序的元素序列中,排序完成。

        直接插入排序的时间复杂度为O(n^2),空间复杂度为O(1)。虽然时间复杂度较高,但是对于小规模数据的排序效率较高,并且具有稳定性。

2.2 代码实现 

以下是C语言编写的直接插入排序并计数比较次数的程序:

#include <stdio.h>
#define MAXSIZE 100void InsertionSort(int A[], int n, int *cnt) {int i, j, temp;for(i = 1; i < n; i++) {temp = A[i];for(j = i - 1; j >= 0; j--) {(*cnt)++;if(A[j] > temp)A[j + 1] = A[j];elsebreak;}A[j + 1] = temp;}
}int main() {int A[MAXSIZE];int n, cnt = 0;printf("请输入待排序数列元素个数(不超过%d):", MAXSIZE);scanf("%d", &n);printf("请输入待排序数列:");for(int i = 0; i < n; i++)scanf("%d", &A[i]);InsertionSort(A, n, &cnt);printf("排序后结果:");for(int i = 0; i < n; i++)printf("%d ", A[i]);printf("\n比较次数:%d\n", cnt);return 0;
}

        程序中的 InsertionSort 函数实现了直接插入排序,并使用指针形参 cnt 对比较次数进行计数。主函数中首先输入待排序数列元素个数和数列元素,然后调用 InsertionSort 函数进行排序,并输出排序后的结果和比较次数。

下面是C语言在链式存储结构上设计直接插入排序算法的示例代码:

typedef struct Node {int data;struct Node *next;
}Node;void insertSort(Node **head) {if (*head == NULL || (*head)->next == NULL) {return;}Node *p = (*head)->next;(*head)->next = NULL; // 设置新的有序链表头节点while (p != NULL) {Node *q = p->next;Node *prev = NULL;Node *cur = *head;while (cur != NULL && cur->data < p->data) {prev = cur;cur = cur->next;}if (prev == NULL) { // 插入到头节点之前p->next = *head;*head = p;} else { // 插入到prev和cur之间prev->next = p;p->next = cur;}p = q;}
}

        此代码首先对链表的头节点进行判断,若链表为空或只有一个节点则不需要排序。然后指针p指向头节点的后继节点,将头节点的后继节点设为空,新的有序链表头节点为原链表的头节点。接下来,对p的每个节点进行插入排序操作,找到p应该插入的位置并插入。最后返回排好序的链表头节点。

3、折半插入排序

3.1 算法思想

        折半插入排序算法是插入排序算法的一种变种。它的基本思想是将待排序的序列分成两部分,前半部分为已排序好的部分,后半部分为未排序的部分。排序过程中,每次从未排序的部分中选出一个元素,通过折半查找的方式,找到它应该插入到已排序的部分中的哪个位置,然后再将的元素插入到已排序的部分中。

具体实现步骤如下:

1. 将待排序序列的第一个元素作为已排序的部分,剩下的元素作为未排序的部分。

2. 从未排序的部分中选出一个元素,通过二分查找找到它应该插入到已排序的部分中的位置。

3. 将该元素插入到已排序的部分中,同时将已排序的部分的长度增加1,未排序的部分的长度减少1。

4. 重复步骤2和步骤3,直到未排序的部分为空。

        折半插入排序算法相比于普通的插入排序算法,虽然查找的时间复杂度由O(n)降低为O(log n),但是这并不影响算法的总体时间复杂度,依然是O(n^2)。不过,在某些特定的场景下,折半插入排序算法的效率可能会比普通的插入排序算法更高。

3.2 代码实现 

        折半插入排序是插入排序的一种优化算法,它利用二分查找的思想来确定插入位置,从而减少比较和移动的次数,提高排序效率。

下面是C语言实现折半插入排序的示例代码:

void binary_insertion_sort(int arr[], int len) {int i, j, left, right, mid, tmp;for (i = 1; i < len; i++) {tmp = arr[i];left = 0;right = i - 1;// 找到插入位置while (left <= right) {mid = (left + right) / 2;if (tmp < arr[mid]) {right = mid - 1;} else {left = mid + 1;}}// 移动元素for (j = i - 1; j >= left; j--) {arr[j + 1] = arr[j];}// 插入元素arr[left] = tmp;}
}

        该算法的时间复杂度为O(nlogn),空间复杂度为O(1)。

4、希尔排序

4.1 算法思想

        希尔排序算法是插入排序的一种改进算法,也称为缩小增量排序。希尔排序的基本思想是将待排序序列分割成若干个子序列,对每个子序列进行插入排序,然后不断减小步长,直到步长为1,完成排序。

        具体实现时,先确定一个增量,在每个增量下将序列分成若干个小组,对每个小组进行插入排序。然后逐渐减小增量,重复上述操作,直到增量减小为1,再进行一次插入排序。不同的增量序列会影响希尔排序的效率,一般采用Hibbard增量序列或Sedgewick增量序列来提高排序效率。

        希尔排序算法时间复杂度为O(nlogn)到O(n^2)之间,取决于增量序列的选择。在一般情况下,希尔排序具有较好的排序效率和稳定性,特别适用于数据量较大、无序性较强的序列。

4..2 代码实现 

下面是C语言实现希尔排序的代码:

void shell_sort(int arr[], int len)
{int gap, i, j, temp;for (gap = len / 2; gap > 0; gap /= 2) {  // gap为步长,每次减半直到为1for (i = gap; i < len; i++) {temp = arr[i];for (j = i - gap; j >= 0 && arr[j] > temp; j -= gap) {arr[j + gap] = arr[j];  // 向后移动gap位}arr[j + gap] = temp;  // 插入到正确位置}}
}

        该代码首先将整个待排序序列分成若干个子序列,按照步长进行插入排序。然后逐渐缩小步长,直至为1,最后进行一次普通的插入排序,完成整个排序过程。

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

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

相关文章

electron快速入门

新建electronstu01文件夹 以管理员身份运行powershell&#xff0c;切换到该文件下 npm init -y安装依赖包 npm install --save-dev electron失败 npm install -g cnpm --registryhttps://registry.npm.taobao.org cnpm install --save-dev electron修改 package.json &qu…

正则表达式的应用(前端写法)

文章目录 1、匹配字符串中&#xff0c;a标签的href值2、校验邮箱3、校验手机号码3、待添加... 1、匹配字符串中&#xff0c;a标签的href值 (1) 代码 /*** description 匹配字符串中&#xff0c;a标签的href值* param {string} str 匹配的字符串* return {Array} 返回href值*/…

冒泡排序与选择排序(最low的两兄弟)

个人主页&#xff1a;Lei宝啊 愿所有美好如期而遇 前言&#xff1a; 在我们的生活中&#xff0c;无处不在用到排序&#xff0c;比如说成绩的排名&#xff0c;淘宝&#xff0c;京东等等商品在各个方面的排序&#xff0c;这样看来一个好的算 法很重要&#xff0c;接下来我们要先…

JVM对象创建与内存分配机制

对象的创建 对象创建的主要流程: ​ 1.类加载检查 虚拟机遇到一条new指令时&#xff0c;首先将去检查这个指令的参数是否能在常量池中定位到一个类的符号引用&#xff0c;并且检查这个符号引用代表的类是否已被加载、解析和初始化过。如果没有&#xff0c;那必须先执行相应…

Lua学习笔记:debug.sethook函数

前言 本篇在讲什么 使用Lua的debug.setHook函数 本篇需要什么 对Lua语法有简单认知 依赖Sublime Text工具 本篇的特色 具有全流程的图文教学 重实践&#xff0c;轻理论&#xff0c;快速上手 提供全流程的源码内容 ★提高阅读体验★ &#x1f449; ♠ 一级标题 &…

【AI视野·今日NLP 自然语言处理论文速览 第三十八期】Thu, 21 Sep 2023

AI视野今日CS.NLP 自然语言处理论文速览 Thu, 21 Sep 2023 Totally 57 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Computation and Language Papers Chain-of-Verification Reduces Hallucination in Large Language Models Authors Shehzaad Dhuliawala, Mojt…

华为杯数学建模比赛经验分享

再过一周左右,第二十届华为杯数学建模比赛就要开赛了&#xff0c;所以今天分享一下个人数学建模比赛的经验。 今天给大家分享一期关于华为杯数学建模比赛的经验分享&#xff0c;我将从以下三个方面展开说明&#xff1a; &#xff08;1&#xff09;如何准备数学建模比赛&#x…

系统集成|第十七章(笔记)

目录 第十七章 变更管理17.1 项目变更的基本概念17.2 变更管理的基本原则17.3 角色职位与工作程序17.4 相关事宜 上篇&#xff1a;第十六章、信息&#xff08;文档&#xff09;和配置管理 下篇&#xff1a;第十八章、安全管理 第十七章 变更管理 17.1 项目变更的基本概念 变更…

获取热门电影算法

功能#2&#xff1a;获取热门电影 为我们的“Netflix”项目实现“获取热门电影”功能。 我们将介绍以下内容 描述 解决方案 复杂性措施 时间复杂度 空间复杂度 描述# 现在&#xff0c;我们需要建立一个标准&#xff0c;以便将来自多个国家的顶级电影组合成一个单一的顶级电影…

24. 图论 - 图的表示种类

Hi,你好。我是茶桁。 之前的一节课中,我们了解了图的来由和构成,简单的理解了一下图的一些相关概念。那么这节课,我们要了解一下图的表示,种类。相应的,我们中间需要穿插一些新的知识点用于更好的去理解图,比如说邻接矩阵。 图的表示 我们一般用什么样的形式来表示图…

Linux su sudo命令

1、su命令——切换用户 1.1、切换到root用户(需要密码) su - root 1.2、切换到其他用户&#xff0c;比如jackma&#xff08;无需密码&#xff09; su - jackma 2、sudo命令——给普通用户添加root权限 2.1、用法 切换到root用户&#xff0c;执行visudo命令&#xff0c;会自动…

配置pytorchGPU虚拟环境-python3.7

cuda版本的pytorch包下载地址戳这里 winR->输入cmd->输nvcc -V回车 cuda 11.0 输入以下命令来查找 CUDA 的安装路径&#xff1a; Windows: where nvcc 输入以下命令来查找 cuDNN 的版本号&#xff1a; Windows: where cudnn* cuDNN 8.0 本机安装的是cuda 11.0&…

C语言数组和指针笔试题(三)(一定要看)

目录 字符数组四例题1例题2例题3例题4例题5例题6例题7 结果字符数组五例题1例题2例题3例题4例题5例题6例题7结果字符数组六例题1例题2例题3例题4例题5例题6例题7 结果 感谢各位大佬对我的支持,如果我的文章对你有用,欢迎点击以下链接 &#x1f412;&#x1f412;&#x1f412;个…

第二证券:迎政策助力,新型工业化爆发,德恩精工3日涨超60%

新式工业化概念26日盘中大幅拉升&#xff0c;到发稿&#xff0c;德恩精工、精伦电子、天永智能等涨停&#xff0c;固高科技涨约8%&#xff0c;亚威股份涨逾6%&#xff0c;金自天正、创世纪涨约5%。 值得注意的是&#xff0c;精伦电子已接连5个交易日涨停&#xff0c;公司昨日晚…

2023-09-21 buildroot linux 查看应用的log打印信息,命令cat /var/log/messages

一、应用会调用syslog 把打印信息输出到串口&#xff0c;debug 串口会打印kernel的log和上层应用的的log。 二、linux 命令cat /var/log/messages查看应用log

Spire.OCR for .NET 1.9.0 Crack

Spire.OCR for .NET 是一个专业的 OCR 库&#xff0c;用于从 JPG、PNG、GIF、BMP 和 TIFF 格式的图像中读取文本。开发人员可以轻松地在 C# 和 VB.NET 的 .NET 应用程序中添加 OCR 功能。它支持常用的图像格式&#xff0c;并提供从图像中​​读取多个字符和字体、粗体和斜体样式…

如何给Nginx配置访问IP白名单

一、Nginx配置访问IP白名单 有时部署的应用需要只允许某些特定的IP能够访问&#xff0c;其他IP不允许访问&#xff0c;这时&#xff0c;就要设置访问白名单&#xff1b; 设置访问白名单有多种方式&#xff1a; 1.通过网络防火墙配置&#xff0c;例如阿里云/华为云管理平台 2.…

Selenium自动化测试 —— 通过cookie绕过验证码的操作!

验证码的处理 对于web应用&#xff0c;很多地方比如登录、发帖都需要输入验证码&#xff0c;类型也多种多样&#xff1b;登录/核心操作过程中&#xff0c;系统会产生随机的验证码图片&#xff0c;进行验证才能进行后续操作 解决验证码的方法如下&#xff1a; 1、开发做个万能…

ChatGPT 现在可以看、听和说话了!

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

玩转Mysql系列 - 第23篇:mysql索引管理详解

这是Mysql系列第23篇。 环境&#xff1a;mysql5.7.25&#xff0c;cmd命令中进行演示。 代码中被[]包含的表示可选&#xff0c;|符号分开的表示可选其一。 关于索引的&#xff0c;可以先看一下前2篇文章&#xff1a; 什么是索引&#xff1f; mysql索引原理详解 本文主要介…