当前位置: 首页 > news >正文

深入浅出:插入排序算法完全解析

1. 什么是插入排序?

插入排序(Insertion Sort)是一种简单的排序算法,其基本思想与我们整理扑克牌的方式非常相似。我们将扑克牌从第二张开始依次与前面已排序的牌进行比较,将其插入到合适的位置,直到所有牌都有序。

插入排序是一种逐步构建有序序列的算法,每次从未排序部分中取出一个元素,并将其插入到已排序部分的合适位置。

2. 插入排序的基本思想

插入排序的基本思想是逐步构建一个有序的序列。它将数组分为两部分:已排序部分和未排序部分。每次将未排序部分的第一个元素插入到已排序部分的合适位置,直到整个数组有序。

插入排序的具体步骤:

  1. 将第一个元素看作已排序的部分。
  2. 从第二个元素开始,将当前元素与已排序部分的元素进行比较。
  3. 如果当前元素小于已排序部分的元素,则将已排序部分的元素向右移动一个位置,为当前元素腾出空间。
  4. 将当前元素插入到合适的位置。
  5. 重复步骤2到步骤4,直到所有元素都插入到正确的位置。

插入排序的过程可以通过下面的动画来帮助理解:

假设我们有以下无序数组:

[5, 2, 9, 1, 5, 6]

插入排序的过程如下:

  1. 初始状态:[5, 2, 9, 1, 5, 6]
  2. 插入第二个元素 2:[2, 5, 9, 1, 5, 6]
  3. 插入第三个元素 9:[2, 5, 9, 1, 5, 6]
  4. 插入第四个元素 1:[1, 2, 5, 9, 5, 6]
  5. 插入第五个元素 5:[1, 2, 5, 5, 9, 6]
  6. 插入第六个元素 6:[1, 2, 5, 5, 6, 9]

最终排序后的数组:[1, 2, 5, 5, 6, 9]

3. 插入排序的伪代码

for i = 1 to n-1:          // 从第二个元素开始current = arr[i]       // 当前元素j = i - 1              // 已排序部分的最后一个元素while j >= 0 and arr[j] > current:   // 逐步向前查找插入位置arr[j + 1] = arr[j]                // 将大于当前元素的值向右移动j -= 1arr[j + 1] = current    // 将当前元素插入合适位置

过程说明:

  • 外循环for i = 1 to n-1):从第二个元素开始,逐步将当前元素插入到已排序的部分。
  • 内循环while j >= 0 and arr[j] > current):比较当前元素与已排序部分的元素,并将大于当前元素的元素向右移动。
  • 插入操作:在找到合适位置后,将当前元素插入到空位置。

4. 插入排序的时间复杂度分析

插入排序的时间复杂度取决于输入数据的顺序。

  • 最优情况(已经排好序):每次比较时都无需移动元素,只进行一次比较。此时时间复杂度为 O(n)
  • 最坏情况(完全逆序):每个元素都需要与已排序部分的每个元素进行比较并移动。因此,时间复杂度为 O(n²)
  • 平均情况:假设数据是随机排列的,插入排序的平均时间复杂度也是 O(n²)

空间复杂度:

插入排序只使用常数级的额外空间(只需一个临时变量来保存当前元素),因此它的空间复杂度是 O(1)

总结:

  • 最佳时间复杂度:O(n),当输入数组已经有序时。
  • 最坏时间复杂度:O(n²),当输入数组完全逆序时。
  • 平均时间复杂度:O(n²),适用于随机排列的数据。
  • 空间复杂度:O(1),是一个原地排序算法。

5. 插入排序的优缺点

优点:

  1. 简单易懂:插入排序的算法实现非常简单,适合用来讲解排序的基本思想。
  2. 空间复杂度低:它是原地排序算法,不需要额外的空间(只需常数级别的空间)。
  3. 适用于小数据量:当数据量较小或数据已经部分有序时,插入排序的效率较高。
  4. 稳定排序:插入排序是一种稳定排序算法,意思是相等的元素不会交换位置,保留原有的顺序。

缺点:

  1. 时间复杂度高:对于大数据量的排序,时间复杂度为 O(n²),性能较差,不适合大规模数据的排序。
  2. 不适用于大数据集:对于大规模数据,插入排序会表现得很慢,通常选择更高效的排序算法,如快速排序、归并排序等。

6. 插入排序的代码实现(Java)

Java 实现:

import java.util.Arrays;public class InsertionSort {public static void insertionSort(int[] arr) {// 从第二个元素开始for (int i = 1; i < arr.length; i++) {int current = arr[i];    // 当前元素int j = i - 1;           // 已排序部分的最后一个元素// 查找插入位置while (j >= 0 && arr[j] > current) {arr[j + 1] = arr[j];  // 将大于当前元素的值向右移动j--;}arr[j + 1] = current;    // 插入当前元素}}public static void main(String[] args) {int[] arr = { 5, 2, 9, 1, 5, 6 };System.out.println("Before sorting: " + Arrays.toString(arr));insertionSort(arr);System.out.println("After sorting: " + Arrays.toString(arr));}
}

输出:

Before sorting: [5, 2, 9, 1, 5, 6]
After sorting: [1, 2, 5, 5, 6, 9]

代码解析:

  1. 初始化:从数组的第二个元素开始,假设第一个元素已经是有序的。
  2. 查找插入位置:通过 while 循环,逐步将当前元素与已排序部分的元素进行比较,并向右移动大于当前元素的元素。
  3. 插入当前元素:找到正确的插入位置后,将当前元素插入到该位置。

7. 应用场景

  • 小规模数据:当数据量较小或基本有序时,插入排序非常高效。由于它的时间复杂度较低(O(n))在数据已经排序的情况下,插入排序会比其他复杂的排序算法(如快速排序)更快。
  • 实时数据:插入排序适用于不断接收数据并需要立即排序的场景,例如在实时系统中,插入新数据时只需将数据插入到已排序的部分。
  • 链表排序:对于链表结构,插入排序比其他排序算法(如快速排序)更有效,因为链表本身在插入操作时更为高效。

8. 总结

插入排序是一种简单而有效的排序算法,适用于数据量较小或已经部分有序的情况。它的时间复杂度是 O(n²),因此在处理大规模数据时并不高效,但它是稳定的排序算法,并且实现非常简单。理解插入排序的过程和代码可以帮助我们更好地理解其他排序算法的实现和优化。

相关文章:

深入浅出:插入排序算法完全解析

1. 什么是插入排序&#xff1f; 插入排序&#xff08;Insertion Sort&#xff09;是一种简单的排序算法&#xff0c;其基本思想与我们整理扑克牌的方式非常相似。我们将扑克牌从第二张开始依次与前面已排序的牌进行比较&#xff0c;将其插入到合适的位置&#xff0c;直到所有牌…...

【Keras图像处理入门:图像加载与预处理全解析】

本文将全面讲解如何使用Keras进行图像加载、预处理和数据增强&#xff0c;为深度学习模型准备高质量的图像数据。 一、单张图像处理基础 1. 图像加载与尺寸调整 from keras.preprocessing import image# 加载图像并调整尺寸 img image.load_img(example.jpg, target_size(1…...

企业级AI办公落地实践:基于钉钉/飞书的标准产品解决方案

一、平台化AI的崛起&#xff1a;开箱即用的智能革命 2024年企业AI应用调研数据显示&#xff1a; 73%的中型企业选择平台标准产品而非自研头部SaaS平台AI功能渗透率达89%典型ROI周期从18个月缩短至3-6个月 核心优势对比&#xff1a; 维度自研方案平台标准产品部署周期6-12个…...

对于邮箱地址而言,短中划线(Hyphen, -)和长中划线(Em dash, —)有区别吗

对于邮箱地址而言&#xff0c;**短中划线&#xff08;Hyphen, -&#xff09;和长中划线&#xff08;Em dash, —&#xff09;**有明确的区别&#xff1a; 短中划线&#xff08;Hyphen, -&#xff09;&#xff1a; 在邮箱地址中&#xff0c;短中划线是可以使用的&#xff0c;通常…...

C++ STL(三)list

目录 list是什么 构造函数 元素访问 容量操作 修改 迭代器 code实例 实现简单的list forward_list是什么 构造函数 元素访问 容量 修改 迭代器 code实例 实现一个简单的forward_list list是什么 std::list 是 C 标准模板库&#xff08;STL&#xff09;中的一个…...

Vue3+TypeScript 封装一个好用的防抖节流自定义指令

一、前言&#xff1a;为什么需要防抖节流&#xff1f; 在前端开发中&#xff0c;高频触发的事件&#xff08;如滚动、输入、点击等&#xff09;容易导致性能问题。防抖&#xff08;debounce&#xff09; 和 节流&#xff08;throttle&#xff09; 是两种常用的优化手段&#x…...

HarmonyOS+Django实现图片上传

话不多说&#xff0c;直接看代码&#xff1a; HarmonyOS部分代码 import { router } from "kit.ArkUI" import PreferencesUtil from "../utils/PreferencesUtil" import { photoAccessHelper } from "kit.MediaLibraryKit" import fs from oh…...

vscode 版本

vscode官网 Visual Studio Code - Code Editing. Redefined 但是官网只提供最新 在之前的版本就要去github找了 https://github.com/microsoft/vscode/releases 获取旧版本vscode安装包的方法_vscode 老版本-CSDN博客...

Python 爬虫实战案例 - 获取拉勾网招聘职位信息

引言 拉勾网&#xff0c;作为互联网招聘领域的佼佼者&#xff0c;汇聚了海量且多样的职位招聘信息。这些信息涵盖了从新兴科技领域到传统行业转型所需的各类岗位&#xff0c;无论是初出茅庐的应届生&#xff0c;还是经验丰富的职场老手&#xff0c;都能在其中探寻到机遇。 对…...

结构型模式---外观模式

概念 外观模式是一种结构型设计模式&#xff0c;它的核心思想是为复杂的子系统提供一个统一的接口&#xff0c;简化客户端与子系统的交互。外观模式通过引入一个高层接口&#xff0c;隐藏子系统的复杂性&#xff0c;使客户端更容易使用。 适用场景 用于客户端无需具体操作子…...

Docker数据卷操作实战

什么是数据卷 数据卷 是一个可供一个或多个容器使用的特殊目录&#xff0c;它绕过 UFS&#xff0c;可以提供很多有用的特性: 数据卷 可以在容器之间共享和享用对 数据卷 的修改立马生效对 数据卷 的更新&#xff0c;不会影响镜像数据卷 默认会一直存在&#xff0c;即时容器被…...

技术速递|Copilot Usage Advanced Dashboard 教程

作者&#xff1a;Xuefeng Yin 排版&#xff1a;Alan Wang Copilot Usage Advanced Dashboard 是为了充分利用 GitHub Copilot API 中的几乎所有数据&#xff0c;用到的 API 有&#xff1a; List teams of an onganization Get a summary of Copilot metrics for a team Get C…...

【Python爬虫(90)】以Python爬虫为眼,洞察金融科技监管风云

【Python爬虫】专栏简介:本专栏是 Python 爬虫领域的集大成之作,共 100 章节。从 Python 基础语法、爬虫入门知识讲起,深入探讨反爬虫、多线程、分布式等进阶技术。以大量实例为支撑,覆盖网页、图片、音频等各类数据爬取,还涉及数据处理与分析。无论是新手小白还是进阶开发…...

Shell学习(1/6) 教程-变量

一、教程 Shell 是一个用 C 语言编写的程序&#xff0c;它是用户使用 Linux 的桥梁。Shell 既是一种命令语言&#xff0c;又是一种程序设计语言。 Shell 是指一种应用程序&#xff0c;这个应用程序提供了一个界面&#xff0c;用户通过这个界面访问操作系统内核的服务。 Shell…...

《Qt窗口动画实战:Qt实现呼吸灯效果》

Qt窗口动画实战&#xff1a;Qt实现呼吸灯效果 在嵌入式设备或桌面应用中&#xff0c;呼吸灯效果是一种常见且优雅的UI动画&#xff0c;常用于指示系统状态或吸引用户注意。本文将介绍如何使用Qt动画框架实现平滑的呼吸灯效果。 一、实现原理 利用Qt自带的动画框架来实现&…...

RabbitMQ系列(六)基本概念之Routing Key

在 RabbitMQ 中&#xff0c;Routing Key&#xff08;路由键&#xff09; 是用于将消息从交换机&#xff08;Exchange&#xff09;路由到指定队列&#xff08;Queue&#xff09;的关键参数。其核心作用是通过特定规则匹配绑定关系&#xff0c;确保消息被正确分发。以下是其核心机…...

Spring Boot 集成 Kafka

在现代软件开发中&#xff0c;分布式系统和微服务架构越来越受到关注。为了实现系统之间的异步通信和解耦&#xff0c;消息队列成为了一种重要的技术手段。Kafka 作为一种高性能、分布式的消息队列系统&#xff0c;被广泛应用于各种场景。而 Spring Boot 作为一种流行的 Java 开…...

CentOS中shell脚本对多台机器执行下载安装

1.建立免密ssh连接 详情见这篇&#xff1a; CentOS建立ssh免密连接&#xff08;含流程剖析&#xff09;-CSDN博客 2.脚本编写 我这里只是简单写了个demo进行演示&#xff0c;如果服务器很多可以先暂存成文件再逐行读取host进行连接并执行命令 用node1去ssh连接node2和node…...

浅析eBPF

目录 一、eBPF 原理 二、eBPF 已可投入使用的场景 三、eBPF 与 Jaeger/Zipkin 的区别及先进性 四、使用 eBPF 的开源软件 五、开源软件的局限性或待实现功能 猫哥说 一、eBPF 原理 eBPF (extended Berkeley Packet Filter) 是一种内核技术&#xff0c;允许用户在内核空间…...

HTML 基础 (快速入门)详细步骤和示例

目录 创建基本的 HTML 文件 添加内容到页面 页面布局与链接 HTML&#xff08;超文本标记语言&#xff09;是构建网页的基础技术&#xff0c;以下是 HTML 基础的详细步骤和示例&#xff1a; 创建基本的 HTML 文件 步骤一&#xff1a;新建文件 在本地计算机上选择一个合适的…...

MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例

一、MySQL 隔离级别 MySQL 提供了四种隔离级别,用于控制事务之间的并发访问以及数据的可见性,不同隔离级别对脏读、幻读、不可重复读这几种并发数据问题有着不同的处理方式,具体如下: 隔离级别脏读不可重复读幻读性能特点及锁机制读未提交(READ UNCOMMITTED)允许出现允许…...

1.3 VSCode安装与环境配置

进入网址Visual Studio Code - Code Editing. Redefined下载.deb文件&#xff0c;然后打开终端&#xff0c;进入下载文件夹&#xff0c;键入命令 sudo dpkg -i code_1.100.3-1748872405_amd64.deb 在终端键入命令code即启动vscode 需要安装插件列表 1.Chinese简化 2.ros …...

OkHttp 中实现断点续传 demo

在 OkHttp 中实现断点续传主要通过以下步骤完成&#xff0c;核心是利用 HTTP 协议的 Range 请求头指定下载范围&#xff1a; 实现原理 Range 请求头&#xff1a;向服务器请求文件的特定字节范围&#xff08;如 Range: bytes1024-&#xff09; 本地文件记录&#xff1a;保存已…...

高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数

高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数 在软件开发中,单例模式(Singleton Pattern)是一种常见的设计模式,确保一个类仅有一个实例,并提供一个全局访问点。在多线程环境下,实现单例模式时需要注意线程安全问题,以防止多个线程同时创建实例,导致…...

Java毕业设计:WML信息查询与后端信息发布系统开发

JAVAWML信息查询与后端信息发布系统实现 一、系统概述 本系统基于Java和WML(无线标记语言)技术开发&#xff0c;实现了移动设备上的信息查询与后端信息发布功能。系统采用B/S架构&#xff0c;服务器端使用Java Servlet处理请求&#xff0c;数据库采用MySQL存储信息&#xff0…...

为什么要创建 Vue 实例

核心原因:Vue 需要一个「控制中心」来驱动整个应用 你可以把 Vue 实例想象成你应用的**「大脑」或「引擎」。它负责协调模板、数据、逻辑和行为,将它们变成一个活的、可交互的应用**。没有这个实例,你的代码只是一堆静态的 HTML、JavaScript 变量和函数,无法「活」起来。 …...

【SpringBoot自动化部署】

SpringBoot自动化部署方法 使用Jenkins进行持续集成与部署 Jenkins是最常用的自动化部署工具之一&#xff0c;能够实现代码拉取、构建、测试和部署的全流程自动化。 配置Jenkins任务时&#xff0c;需要添加Git仓库地址和凭证&#xff0c;设置构建触发器&#xff08;如GitHub…...

uniapp 集成腾讯云 IM 富媒体消息(地理位置/文件)

UniApp 集成腾讯云 IM 富媒体消息全攻略&#xff08;地理位置/文件&#xff09; 一、功能实现原理 腾讯云 IM 通过 消息扩展机制 支持富媒体类型&#xff0c;核心实现方式&#xff1a; 标准消息类型&#xff1a;直接使用 SDK 内置类型&#xff08;文件、图片等&#xff09;自…...

Ubuntu系统多网卡多相机IP设置方法

目录 1、硬件情况 2、如何设置网卡和相机IP 2.1 万兆网卡连接交换机&#xff0c;交换机再连相机 2.1.1 网卡设置 2.1.2 相机设置 2.3 万兆网卡直连相机 1、硬件情况 2个网卡n个相机 电脑系统信息&#xff0c;系统版本&#xff1a;Ubuntu22.04.5 LTS&#xff1b;内核版本…...

数据结构:递归的种类(Types of Recursion)

目录 尾递归&#xff08;Tail Recursion&#xff09; 什么是 Loop&#xff08;循环&#xff09;&#xff1f; 复杂度分析 头递归&#xff08;Head Recursion&#xff09; 树形递归&#xff08;Tree Recursion&#xff09; 线性递归&#xff08;Linear Recursion&#xff09;…...