插入排序:一种简单而有效的排序算法

插入排序:一种简单而有效的排序算法

  • 一、什么是插入排序?
  • 二、插入排序的步骤
  • 三、插入排序的C语言实现
  • 四、插入排序的性能分析
  • 五、插入排序的优化
  • 六、总结

在我们日常生活和工作中,排序是一种非常常见的操作。比如,我们可能需要对一堆无序的文件、一组杂乱的数据或者一堆扑克牌进行排序。在计算机科学中,排序同样是一个核心问题,而插入排序就是解决这一问题的一种基础而有效的方法。

一、什么是插入排序?

插入排序(Insertion Sort)是一种简单直观的排序算法。它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。插入排序在实现上,通常采用in-place排序(即只需用到O(1)的额外空间的排序),因而在从后向前扫描过程中,需要反复把已排序元素逐步向后挪位,为最新元素提供插入空间。

具体来说,插入排序的工作方式就像我们许多人排序一手扑克牌。开始时,我们的左手为空并且桌子上的牌面向下。然后,我们每次从桌子上拿走一张牌并将它插入左手中正确的位置。为了找到一张牌的正确位置,我们从右到左将它与已在手中的每张牌进行比较。拿在左手上的牌总是排序好的,原来这些牌是桌子上牌堆中顶部的牌。

二、插入排序的步骤

插入排序的基本操作是将一个数据元素插入到已经排好序的有序数据中,从而得到一个新的、个数加一的有序数据,算法适用于少量数据的排序,时间复杂度为O(n^2)。是稳定的排序方法。

插入排序的步骤如下:

从第一个元素开始,该元素可以认为已经被排序;
取出下一个元素,在已经排序的元素序列中从后向前扫描;
如果该元素(已排序)大于新元素,将该元素移到下一位置;
重复步骤3,直到找到已排序的元素小于或者等于新元素的位置;
将新元素插入到该位置后;
重复步骤2~5。
在这里插入图片描述

三、插入排序的C语言实现

下面是一个简单的插入排序的C语言实现:

c
#include <stdio.h>  void insertionSort(int arr[], int n) {  int i, key, j;  for (i = 1; i < n; i++) {  key = arr[i];  j = i - 1;  /* Move elements of arr[0..i-1], that are  greater than key, to one position ahead  of their current position */  while (j >= 0 && arr[j] > key) {  arr[j + 1] = arr[j];  j = j - 1;  }  arr[j + 1] = key;  }  
}  /* A utility function to print array of size n */  
void printArray(int arr[], int n) {  int i;  for (i = 0; i < n; i++)  printf("%d ", arr[i]);  printf("\n");  
}  /* Test the above functions */  
int main() {  int arr[] = {12, 11, 13, 5, 6};  int n = sizeof(arr) / sizeof(arr[0]);  insertionSort(arr, n);  printf("Sorted array: \n");  printArray(arr, n);  return 0;  
}

在这个例子中,我们首先定义了一个insertionSort函数,它接受一个整数数组arr和数组的长度n作为参数。然后,我们使用一个for循环来遍历数组中的每个元素。对于每个元素,我们将其保存在变量key中,并将j初始化为当前元素的索引减一。然后,我们使用一个while循环来将大于key的元素向后移动一位,直到找到key的正确位置。最后,我们将key插入到正确的位置。

在main函数中,我们定义了一个需要排序的数组arr,并计算了数组的长度n。然后,我们调用insertionSort函数对数组进行排序,并使用printArray函数打印排序后的数组。

四、插入排序的性能分析

插入排序的时间复杂度是O(n2),其中n是待排序元素的数量。在最坏的情况下,即输入序列是逆序的情况下,每次插入都需要移动大量的元素,因此时间复杂度达到O(n2)。然而,在最好的情况下,即输入序列已经是有序的情况下,插入排序的时间复杂度可以降低到O(n)。这是因为在这种情况下,每次插入操作都不需要移动任何元素。

尽管插入排序的时间复杂度相对较高,但它在实际应用中仍然有其价值。特别是当待排序的数据量较小,或者数据部分有序时,插入排序可能比其他更复杂的排序算法更有效。此外,插入排序是一种稳定的排序算法,即相等的元素的顺序在排序后不会改变。这对于某些需要保持相等元素相对顺序的应用场景来说是非常重要的。

五、插入排序的优化

虽然插入排序的基本形式在大多数情况下的性能并不是最优的,但可以通过一些优化手段来提高其效率。

二分插入排序:在基本插入排序中,我们逐个比较和移动元素。而在二分插入排序中,我们使用二分查找来确定新元素应该插入的位置,从而减少比较次数。但是,元素移动的次数仍然是相同的。

希尔排序:也被称为缩小增量排序,是插入排序的一种高效版本。希尔排序首先比较较远的元素,然后逐步减小排序的间隔。当间隔为1时,算法就变成了普通的插入排序。通过这种方式,希尔排序能够在早期阶段消除大量的无序情况,使得后续的插入排序更加高效。

六、总结

插入排序是一种简单直观的排序算法,它通过将未排序的元素插入到已排序的序列中来逐步构建有序序列。虽然它的时间复杂度在最坏情况下是O(n^2),但在数据量较小或数据部分有序时,插入排序可以表现得相当不错。此外,插入排序是稳定的,能够保持相等元素的相对顺序。

通过了解插入排序的工作原理和实现方式,我们可以更好地理解排序算法的基础,并为学习更复杂的排序算法打下坚实的基础。在实际应用中,我们可以根据具体的数据特性和需求来选择合适的排序算法,以达到最优的排序效果。

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

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

相关文章

Echo框架:高性能的Golang Web框架

Echo框架&#xff1a;高性能的Golang Web框架 在Golang的Web开发领域&#xff0c;选择一个适合的框架是构建高性能和可扩展应用程序的关键。Echo是一个备受推崇的Golang Web框架&#xff0c;以其简洁高效和强大功能而广受欢迎。本文将介绍Echo框架的基本特点、使用方式及其优势…

Golang协程详解

一.协程的引入 1.通过案例文章引入并发,协程概念 见:[go学习笔记.第十四章.协程和管道] 1.协程的引入,调度模型&#xff0c;协程资源竞争问题 通过上面文章可以总结出Go并发编程原理: 在一个处理进程中通过关键字 go 启用多个协程&#xff0c;然后在不同的协程中完成不同的子任…

智慧公厕建设的重要性

智慧公厕建设一直被视为提升城市管理水平的重要举措。作为一个关键的城市基础设施&#xff0c;智慧公厕不仅可以改善公共卫生管理&#xff0c;还能提升城市居民的社会民生生活质量。此外&#xff0c;智慧公厕建设还能促进城市的可持续发展&#xff0c;降低能源消耗&#xff0c;…

科研绘图一:箱线图(添加贝赛尔曲线)

R语言绘图系列—箱线图贝赛尔曲线 &#xff08;一&#xff09;: 科研绘图一&#xff1a;箱线图&#xff08;添加贝赛尔曲线&#xff09; 文章目录 R语言绘图系列---箱线图贝赛尔曲线&#xff08;一&#xff09;: 科研绘图一&#xff1a;箱线图&#xff08;添加贝赛尔曲线&…

数据结构/C++:红黑树

数据结构/C&#xff1a;红黑树 概念实现基本结构插入uncle为红色节点uncle为黑色节点 总代码展示 概念 红黑树是一种二叉搜索树&#xff0c;一般的二叉搜索会发送不平衡现象&#xff0c;导致搜索效率下降&#xff0c;于是学者们开始探索如何让二叉搜索树保持平衡&#xff0c;这…

unity学习(60)——选择角色界面--MapHandler2-MapHandler.cs

1.新建一个脚本&#xff0c;里面有static变量loadingPlayerList using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks;namespace Assets.Scripts.Model {internal class LoadData{public static List<Pl…

R语言中的常用基础绘图函数 直方图,箱线图,条形图,散点图

目录 R语言中的绘图参数 绘图函数 1.plot函数绘制散点图 2.hist函数绘制直方图 如何修饰直方图? 如何在直方图上标注各组频数&#xff1f; 使用text函数把某些信息标注在直方图上 如何在直方图上添加概率密度曲线&#xff1f; 3.boxplot函数绘制箱线图 4.barplot函数…

JVM虚拟机:通过jconsole远程连接解决JVM报错

本文重点 前面我们介绍过的一些工具都是使用命令行的方式来帮助我们完成&#xff0c;本文我们将使用一种图形化界面的方式来远程连接&#xff0c;然后完成关于JVM的检测任务。 jconsole jconsole是一个JVM的检测工具&#xff0c;这个工具任何安装了Java的电脑上都有的&#…

手机网络连接性能API接口:查询手机网络连接性能状态

手机在网状态查询服务是一项非常方便的服务&#xff0c;可以帮助我们随时了解一个手机号码的在网状态。不论是查询自己的手机号码&#xff0c;还是查询他人的手机号码&#xff0c;这个服务都可以帮助我们获取准确的信息。今天&#xff0c;我想和大家介绍一个非常好用的手机在网…

GitHub Actions持续部署

一、概述 1.1Github Action介绍 什么是Github Action ? GitHub Actions是GitHub提供的CI/CD&#xff08;持续集成/持续部署&#xff09;服务。它允许你在GitHub仓库中自动化、定制和执行你的软件开发工作流。你可以发现、创建和分享用于执行任何你想要的工作的操作&#xff0…

《计算机视觉中的深度学习》之目标检测算法原理

参考&#xff1a;《计算机视觉中的深度学习》 概述 目标检测的挑战&#xff1a; 减少目标定位的准确度减少背景干扰提高目标定位的准确度 目标检测系统常用评价指标&#xff1a;检测速度和精度 提高精度&#xff1a;有效排除背景&#xff0c;光照和噪声的影响 提高检测速度…

Spark-Transformation以及Action开发实战

文章目录 创建RDDTransformation以及ActionTransformation开发Action开发RDD持久化共享变量创建RDD RDD是Spark的编程核心,在进行Spark编程是,首要任务就是创建一个初始的RDDSpark提供三种创建RDD方式:集合、本地文件、HDFS文件 集合:主要用于本地测试,在实际部署到集群运…

FAN3224TMX门极驱动器中文资料PDF数据手册引脚图参数价格图片功能特性

产品概述&#xff1a; FAN3223-25 系列双 4A 门极驱动器以较短的开关间隔提供高峰值电流脉冲&#xff0c;用于在低侧开关应用中驱动 N 沟道增强模式 MOSFET。该驱动器提供 TTL 或 CMOS 输入阈值。内部电路将输出保持在低电平&#xff0c;直到电源电压处于运行范围内&#xff0…

在Docker容器中配置`code-server`以访问宿主机的Docker环境

在Docker容器中配置code-server以访问宿主机的Docker环境 部分内容使用gpt生成&#xff0c;但经过测试可用。 要在code-server容器内部安全地管理和访问宿主机的Docker环境&#xff08;主要是为了访问宿主机的texlive&#xff09;&#xff0c;遵循以下步骤能够确保流畅的集成和…

R语言深度学习-5-深度前馈神经网络

本教程参考《RDeepLearningEssential》 本篇我们将学习如何建立并训练深度预测模型。我们将关注深度前馈神经网络 5.1 深度前馈神经网络 我们还是使用之前提到的H2O包&#xff0c;详细可以见之前的博客&#xff1a;R语言深度学习-1-深度学习入门&#xff08;H2O包安装报错解决…

[scikit-learn] 第一章 初识scikit-learn及内置数据集介绍

文章目录 菜鸡镇贴&#xff01;&#xff01;&#xff01;scikit-learn 简要介绍scikit-learn 安装scikit-learn 数据集介绍数据集API介绍LoadersSamples generator 导入数据集demo 菜鸡镇贴&#xff01;&#xff01;&#xff01; scikit-learn 简要介绍 ​ Scikit learn是一个…

RK3568平台开发系列讲解(基础篇)内核是如何发送事件到用户空间

🚀返回专栏总目录 文章目录 一、相关接口函数二、udevadm 命令三、实验沉淀、分享、成长,让自己和他人都能有所收获!😄 一、相关接口函数 kobject_uevent 是 Linux 内核中的一个函数, 用于生成和发送 uevent 事件。 它是 udev 和其他设备管理工具与内核通信的一种方式。…

SDN网络简单认识(1)——概述

一、概述 软件定义网络&#xff08;Software Defined Networking&#xff0c;SDN&#xff09;是一种网络架构理念&#xff0c;旨在使网络灵活和可编程&#xff0c;从而更好地支持动态和高度可扩展的计算环境。SDN通过抽象网络的控制层&#xff08;决策层&#xff09;和数据层&a…

面试经典-MySQL篇

一、MySQL组成 MySQL数据库的连接池&#xff1a;由一个线程来监听一个连接上请求以及读取请求数据&#xff0c;解析出来一条我们发送过去的SQL语句SQL接口&#xff1a;负责处理接收到的SQL语句查询解析器&#xff1a;让MySQL能看懂SQL语句查询优化器&#xff1a;选择最优的查询…

OpenCV 图像重映射函数remap()实例详解

OpenCV 图像重映射函数remap()对图像应用通用几何变换。其原型如下&#xff1a; void remap(InputArray src, OutputArray dst, InputArray map1, InputArray map2, int interpolation&#xff0c; int borderMode BORDER_CONSTANT&#xff0c; const Scalar & borde…