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

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

  • 一、什么是插入排序?
  • 二、插入排序的步骤
  • 三、插入排序的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://www.mzph.cn/news/749874.shtml

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

相关文章

【 c 语言 】指针入门

&#x1f388;个人主页&#xff1a;豌豆射手^ &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 &#x1f917;收录专栏&#xff1a;C语言 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共同学习、交流进步&…

ChatGPT编程—实现小工具软件(文件查找和筛选)

ChatGPT编程—实现小工具软件(文件查找和筛选) 今天借助[小蜜蜂AI][https://zglg.work]网站的ChatGPT编程实现一个功能&#xff1a;根据特定需求结合通配符和其他条件来进行文件查找和筛选。在这个例子中&#xff0c;我们将创建一个函数find_files&#xff0c;它接受用户输入的…

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

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

【Spring Boot】创建你的第一个 Spring Boot 应用

创建你的第一个 Spring Boot 应用 1.环境配置2.步骤详解3.项目结构分析3.1 入口类 DemoApplication3.2 控制器 PathVariableController3.3 控制器 BasicController3.4 模型 User 4.运行 Spring Boot 目前已经成为了 Java 开发领域的框架范式。本篇博客&#xff0c;我将带领大家…

layui table列表重载后保持进度条位置不变

使用layui的table表格组件时&#xff0c;当我们操作了某行的修改后&#xff0c;刷新了页面&#xff0c;进度条则跳回到最上面。 除了layui高版本应该内置有方法解决了此问题&#xff0c;但是低版本需要另外想办法解决。 具体解决方式如下&#xff1a; 1.在编辑操作成功前&am…

【MASM汇编语言快速入门】8086MASM汇编深入理解指令对标志位的影响

8086MASM汇编深入理解指令对标志位的影响 文章目录 8086MASM汇编深入理解指令对标志位的影响0. 指令对标志位影响1. 指令对标志位影响速查表2. flags标志寄存器: 标志位含义解读flags1. 状态标志cf, pf, af, zf, sf, of2. 控制标志df, if, tf 详解&#xff1a;1. 传送指令2. 算…

如何在IDEA 中设置背景图片

在IDEA 中设置背景图片&#xff0c;可以按照以下步骤操作&#xff1a; 1、打开 IntelliJ IDEA 软件&#xff0c;进入代码编辑主界面。 点击编辑窗口上方的“File”菜单项。 2、在下拉子菜单中&#xff0c;选择“Settings”选项&#xff08;如果你使用的是 macOS&#xff0c;可…

Spark-Scala语言实战(1)

在之前的文章中&#xff0c;我们学习了如何在Linux安装Spark以及Scala&#xff0c;想了解的朋友可以查看这篇文章。同时&#xff0c;希望我的文章能帮助到你&#xff0c;如果觉得我的文章写的不错&#xff0c;请留下你宝贵的点赞&#xff0c;谢谢。 Spark及Scala的安装https:/…

【智能算法】保姆级教程-如何使用CEC测试集,以及如何定义自己的优化问题

目录 1.准备工作2.使用CEC2005测试集3.自定义优化问题-无约束问题4.自定义优化问题-有约束问题5.代码实现 1.准备工作 一个CEC2005测试集 一个测试智能算法&#xff0c;比如麻雀搜索算法SSA 2.使用CEC2005测试集 以CEC2005测试集函数F7为例&#xff1a; 3.自定义优化问题…

solr/ES 分词插件Jcseg设置自定义词库

步骤&#xff1a; 1、找到配置文件jcseg-core/target/classes/jcseg.properties修改配置&#xff1a; 下载地址: https://gitee.com/lionsoul/jcseg#5-如何自定义使用词库 lexicon.path {jar.dir}/../custom-word 设置lexicon路径&#xff0c;我们这个配置可以自定义&#xf…

计算机网络-概述

文章目录 1.2 因特网概述1.2.1 网络、互连网&#xff08;互联网&#xff09;和因特网1.2.2 因特网发展的三个阶段1.2.4 因特网的组成 1.3 三种交换方式1.3.1 电路交换1.3.2 分组交换1.3.3 报文交换1.3.4 三种方式对比 1.4 计算机网络的定义1.5 计算机网络的性能指标1.5.1 速率1…

antd5 虚拟列表原理(rc-virtual-list)

github:https://github.com/react-component/virtual-list rc-virtual-list 版本 3.11.4(2024-02-01) 版本&#xff1a;virtual-list-3.11.4 Development npm install npm start open http://localhost:8000/List 组件接收 Props PropDescriptionTypeDefaultchildrenRender …

精读《手写 JSON Parser》

1 引言 JSON.parse 是浏览器内置的 API&#xff0c;但如果面试官让你实现一个怎么办&#xff1f;好在有人已经帮忙做了这件事&#xff0c;本周我们一起精读这篇 JSON Parser with Javascript 文章吧&#xff0c;再温习一遍大学时编译原理相关知识。 2 概述 & 精读 要解析…

【机器学习】分类模型的评价方法

&#x1f33b;个人主页&#xff1a;相洋同学 &#x1f947;学习在于行动、总结和坚持&#xff0c;共勉&#xff01; #学习笔记# 目录 一、混淆矩阵&#xff08;Confusion Matrix&#xff09; 二、评估指标&#xff08;Evaluation metrics&#xff09; 1.正确率(accuracy) …

R统计学3 - 数据分析入门问题41-60

往期R统计学文章: R统计学1 - 基础操作入门问题1-20 R统计学2 - 数据分析入门问题21-40 41. R 语言如何做双坐标图? # 创建模拟数据 year <- 2014:2024 gdp <- data.frame(year, GDP = sort(rnorm(11, 1000, 100))) ur <- data.frame(year, UR = rnorm(11, 5, 1…

计算机网络(7)----应用层

目录 一.应用层的基本概念 1.应用层的基本概述 2.网络应用模型 &#xff08;1&#xff09;客户/服务器模型 &#xff08;2&#xff09;P2P模型 二.应用程序相关 1.DNS系统 &#xff08;1&#xff09;域名与域名服务器 &#xff08;2&#xff09;域名解析过程&#xff…

2024 第一届VCTF 纳新赛 Web方向 题解WP

hackjs 题目描述&#xff1a;A baby oldjs, just warm up. 附件给源码 const express require(express) const fs require(fs) var bodyParser require(body-parser); const app express() app.use(bodyParser.urlencoded({extended: true })); app.use(bodyParser.json…

CI/CD实战-git工具使用 1

版本控制系统 本地版本控制系统 集中化的版本控制系统 分布式版本控制系统 git官网文档&#xff1a;https://git-scm.com/book/zh/v2 Git 有三种状态&#xff1a;已提交&#xff08;committed&#xff09;、已修改&#xff08;modified&#xff09; 和 已暂存&#xff08;sta…

嵌入式硬件设计(一)|利用 NodeMCU-ESP8266 开发板和继电器结合APP“点灯•blinker”制作Wi-Fi智能开关(附有关硬件详细资料)

概述 本文主要讲述利用 NodeMCU-ESP8266 开发板和继电器通过手机 APP “ 点灯 • Blinker ” 制作一款能够由手机控制的WiFi 智能开关&#xff0c;从而实现智能物联。NodeMCU 是基于 Lua 的开源固件&#xff0c;ESP8266-NodeMCU是一个开源硬件开发板&#xff0c;支持WiFi功能&a…

OpenCV4.9.0开源计算机视觉库在 Linux 中安装

返回目录&#xff1a;OpenCV系列文章目录&#xff08;持续更新中......&#xff09; 上一篇&#xff1a;OpenCV 环境变量参考 下一篇&#xff1a;将OpenCV与gcc和CMake结合使用 引言&#xff1a; OpenCV是一个开源的计算机视觉库&#xff0c;由英特尔公司所赞助。它是一个跨…