【数据结构与算法——C语言版】6. 排序算法(3)——插入排序

news2024/11/19 11:18:53

前言

在本系列的上两篇文章分别介绍了两种O(n2)的排序算法——选择排序和冒泡排序,今天是第三种O(n2)的排序算法:插入排序。

插入排序

核心思想

它的基本思想是将一个记录插入到已经排好序的有序表中,从而产生一个新的、记录数增 1 的有序表。
在其实现过程使用双层循环,外层循环对除了第一个元素之外的所有元素,内层循环对当前元素前面有序表进行待插入位置查找,并进行移动。
换句话说,插入排序是从最少元素的有序数列开始,将新的元素插入到该有序数列中某个位置,使插入后的数列依然保持有序
这里,最少元素的有序数列其实指的就是只包含一个元素的数列,也就是 arr[0]。
知道这个概念后,再去理解插入排序的思想就容易多了。

假设要对数组 arr[8] = {7,6,9,3,1,5,2,4} 排序,使排序后保持升序有序,那么插入排序的做法是首先划定第一个有序子序列,也就是arr[0~0];

  1. i = 0, 此时只有一个元素arr[0],已经有序,故当前有序子序列为 arr[0~0]
  2. i = 1,有序子序列为 arr[0~0],此时将 arr[1] 插入到该子序列中,并保持升序有序,所以arr[1] 被插入到 arr[0] 的前面;此时有序子序列为 arr[0~1] = {6, 7}
  3. i = 2, 有序子序列为 arr[0~1],此时将 arr[2] 插入该子序列中,并保持升序有序,所以 arr[2] 被插入到 arr[1] 的后面(也就是不做操作)。此时有有序子序列为 arr[0~2] = {6, 7, 9}
  4. … 中间的过程都是类似的,这里省略
  5. i = 7 时,有序子序列为 arr[0~6] = {1,2,3,5,6,7,9},此时将 arr[7] 插入该子序列中,并保持升序有序,arr[7] 的新位置应该是当前 arr[3] = 5 的位置,所以这一步要将 arr[7] 正确放到 arr[3]的位置,这个步骤是插入排序中的插入,接下来要详细说明如何将 arr[7] 正确放到 arr[3] 的位置,然后使新的子序列升序有序。

arr[7] 正确的插入到有序子序列 {1,2,3,5,6,7,9} 中,总共分为找到插入位置 + 执行插入操作两步

  • 找到插入位置
    遍历当前子序列,找到比 arr[7] 大的第一个元素,该元素的位置就是arr[7]要插入的位置,这里插入位置是 arr[3]
  • 执行插入操作
    首先用 tmp 记录 arr[7] 的元素值,然后将 arr[6 ~ 3] 依次向右移动一个位置,也就是 arr[6 ~ 3] --> arr[7 ~ 4] ;最后将 tmp 的值放入 arr[3] 就完成了插入操作。
/* 插入一个元素到有序子序列 */
// i 的位置是当前要加入有序子序列的元素所在位置
for (int j = 0; j < i; ++j) { // 遍历有序子序列
	if (arr[j] >= arr[i]) { // 找到插入位置,第一个 >= arr[i] 的元素,插入位置为 j
		// 执行插入操作
		int tmp = arr[i]; // 暂存 arr[i] 的值
		for (int k = i-1; k >= j; --k) { // 移动 arr[i-1 ~ j] 的元素 --> arr[i, j+1]
			arr[k] = arr[k-1];
		}
		arr[k] = tmp; // 将暂存的原 arr[i] 的值插入到目标位置
	}
}

图例

  1. 第一轮:从第二位置的 6 开始比较,比前面 7 小,交换位置。
    在这里插入图片描述
  2. 第二轮:第三位置的 9 比前一位置的 7 大,无需交换位置。
    在这里插入图片描述
  3. 第三轮:第四位置的 3 比前一位置的 9 小交换位置,依次往前比较。
    在这里插入图片描述
  4. 第四轮:第五位置的 1 比前一位置的 9 小,交换位置,再依次往前比较。
    在这里插入图片描述

就这样依次比较到最后一个元素。

代码

/* 插入排序 */
void insertionSort(int arr[], int len){
    for (int i = 1; i < len; i++){
        int key = arr[i];
        int j = i-1;
        while((j >= 0) && (arr[j] > key)) {
            arr[j+1] = arr[j];
            j--;
        }
        arr[j+1] = key;
    }
}

这里演示了插入的另一种实现。思路还是找位置 + 插入。
但之前实现的代码,插入的操作就是一个两层的循环,如果再加上外层的遍历一共需要三层循环,想想看,如何能将两层循环的插入操作合并为一层呢?
直接使 k = i-1, 从 arr[j] 开始,依次执行 arr[j] = arr[j-1] ,直到 arr[j] > arr[i] 即可

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

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

相关文章

软件测试~自动化测试Seleniums---1

一.什么是自动化测试 1.自动化测试介绍 自动化测试指软件测试的自动化&#xff0c;在预设状态下运行应用程序或者系统&#xff0c;预设条件包括正常和异常&#xff0c;最后评估运行结果。将人为驱动的测试行为转化为机器执行的过程。 将测试人员双手解放&#xff0c;将部分测…

机器视觉(十):印刷体字符识别

目录&#xff1a; 机器视觉&#xff08;一&#xff09;&#xff1a;概述 机器视觉&#xff08;二&#xff09;&#xff1a;机器视觉硬件技术 机器视觉&#xff08;三&#xff09;&#xff1a;摄像机标定技术 机器视觉&#xff08;四&#xff09;&#xff1a;空域图像增强 …

Unreal模块创建流程

可以把开发中通用的功能封装成模块,以在不同项目之间复用,这里记录一下创建模块的步骤:在工程的Source文件夹中新建文件夹,命名为模块名称TestCustomModule:如果要区分模块内脚本的公私有权限,则在模块文件夹内创建Public和Private文件夹,这里我没有区分,就不创建了:在模块文件…

Js如何实现一个累加向上漂浮动画

前言 在不久之前,看到一个比较有意思的小程序,就是静神木鱼,可以实现在线敲木鱼,自动敲木鱼,手盘佛珠,静心颂钵的 整个小程序功能比较小巧,大道至简,曾风靡过一阵的,无论在App应用市场上,还是小程序里,一些开发者都赚得盆满钵满,用于缓解当代年轻人的一个焦虑,佛系解压,算是一…

Kubernetes:通过轻量化工具 kubespy 实时观察YAML资源变更

写在前面 分享一个小工具 kubespy 给小伙伴博文内容涉及&#xff1a; 工具的简单介绍下载安装以 kubectl 插件方式使用 Demo 理解不足小伙伴帮忙指正 我所渴求的&#xff0c;無非是將心中脫穎語出的本性付諸生活&#xff0c;為何竟如此艱難呢 ------赫尔曼黑塞《德米安》 简单介…

详解二分查找的两种写法以及二分查找的六种变形

目录 一、二分查找的两种写法 1.1 - 第一种写法&#xff08;左闭右闭&#xff09; 1.2 - 第二种写法&#xff08;左闭右开&#xff09; 二、二分查找的六种变形 2.1 - 查找第一个 target 的元素位置 2.2 - 查找第一个 > target 的元素位置 2.3 - 查找第一个 > ta…

JS类型转换机制

概述 JS中有六种简单数据类型&#xff1a;undefined、null、boolean、string、number、symbol&#xff0c;以及引用类型&#xff1a;object 但是我们在声明的时候只有一种数据类型&#xff0c;只有到运行期间才会确定当前类型let x y ? 1 : a; &#xff0c;x的值在编译阶段…

FPGA基础之内置逻辑门

verilog语言中&#xff0c;针对逻辑门&#xff0c;有许多内置可直接使用的逻辑门&#xff0c;从输入输出数量可分为多输入门和多输出门。 一、多输入门 有单个或多个输入&#xff0c;只有单个输出的逻辑门&#xff0c;包含and(与)&#xff0c;or(或)&#xff0c;xor(异或)&am…

在训练心脏数据集时碰到的问题汇总

在训练心脏数据集时碰到的问题汇总&#xff1a; 1.nii数据处理问题 心脏CT数据集采用的是医学图像常用的压缩文件格式nii&#xff0c;且储存的图像为3D图像&#xff0c;不能直接使用。 首先应导入SimpleITK包&#xff0c;利用如下三个函数进行nii格式文件的提取。 sitk.ReadI…

vlan间的通信

vlan之间要通过三层通信实现互访&#xff0c;三层通信需借助三层设备 如果之前配置了 hybrid模式想删除 命令 undo port link-type hybrid vlan all [Huawei-GigabitEthernet0/0/3]dis this interface GigabitEthernet0/0/3 undo port hybrid vlan 1 这里可以理解为多删了一个…

【python】【数据分析】2022年全国大学生数据分析大赛题解-医药电商销售数据分析

文章目录一、前言二、题目三、题解1&#xff0e;对店铺进行分析&#xff0c;一共包含多少家店铺&#xff0c;各店铺的销售额占比如何&#xff1f;给出销售额占比最高的店铺&#xff0c;并分析该店铺的销售情况。2.对所有药品进行分析&#xff0c;一共包含多少个药品&#xff0c…

Promise和async/await

1、回调地狱 多层回调函数的相互嵌套&#xff0c;就形成了回调地狱。示例代码如下&#xff1a; 回调地狱的缺点&#xff1a; 代码耦合性太强&#xff0c;牵一发而动全身&#xff0c;难以维护大量冗余的代码相互嵌套&#xff0c;代码的可读性变差 1.1、如何解决回调地狱的问题…

手把手实现邮件分类 《Getting Started with NLP》chap2:Your first NLP example

《Getting Started with NLP》chap2&#xff1a;Your first NLP example 感觉这本书很适合我这种菜菜,另外下面的笔记还有学习英语的目的&#xff0c;故大多数用英文摘录或总结 文章目录《Getting Started with NLP》chap2&#xff1a;Your first NLP example2.1 Introducing N…

数据结构与算法【树】

二叉树性质 满二叉树 深度为k&#xff0c;有2k−12^{k}-12k−1个结点的二叉树&#xff0c;为满二叉树。 完全二叉树 完全二叉树的定义如下&#xff1a;在完全二叉树中&#xff0c;除了最底层节点可能没填满外&#xff0c;其余每层节点数都达到最大值&#xff0c;并且最下面…

CSDN第22期周赛(记录一下,不是题解)

希望23年能收获一两本程序员杂志 前言 发现一个问题&#xff0c;codeblocks上编译没问题&#xff0c;在CSDN比赛时&#xff0c;会报错&#xff1a; 1&#xff0c;size()和length()属于unsigned int&#xff0c;所以与之比较大小或者赋值的 i, j 也要用unsigned int&#xf…

巧解 JavaScript 中的嵌套替换

网友 wys 提问&#xff1a;如何仅使用 JavaScript 支持的正则语法&#xff0c;将 <p> <table> <p> <p> </table> <table> <p> <p> </table> <p>中<table>...</table>之间的<p>都替换为<b…

C库函数:stdio.h

stdio.h C 标准库 – <stdio.h> | 菜鸟教程 (runoob.com) 下面是头文件 stdio.h 中定义的变量类型&#xff1a; 序号变量 & 描述1size_t 这是无符号整数类型&#xff0c;它是 sizeof 关键字的结果。2FILE 这是一个适合存储文件流信息的对象类型。3fpos_t 这是一个适…

组件的生命周期

一、组件的生命周期 1、组件的生命周期&#xff1a;至一个组件从 创建——>运行——>销毁的过程 2、声明周期函数&#xff1a;由Vue提供的内置函数&#xff0c;伴随组件生命周期按次序自动运行——>钩子函数 3、生命周期的阶段划分 &#xff08;1&#xff09;创建…

什么是链接?(动态链接库和静态链接库的对比)

什么是链接&#xff1f; 首先我们需要知道&#xff0c;一个源文件&#xff08;以.c为例&#xff09;是经过什么最后形成的一个可执行的文件&#xff08;windows下为.exe文件&#xff09;。 一个.c的源文件&#xff0c;要经历 1.预处理&#xff1a;头文件的展开替换 2.编译&…

skywalking解析-如何在idea中调试skywalking agent

当我从github上下载下来skywalking agent的代码后&#xff0c;面临的第一个问题就是如何调试。因为skywalking agent的运行模式与普通程序运行方式不一样&#xff0c;它是通过java agent方式运行的。本文接下来介绍如何在本地调试skywalking agent源码。 目录一、下载源码二、运…