排序算法 -插入排序
文章目录
- 1.插入排序(Insertion Sort)
- 1.1 简介
- 1.2 插入排序的步骤
- 1.3 插入排序的C实现
- 1.4 插入排序的时间复杂度
- 1.5 插入排序的空间复杂度
- 1.6 插入排序的动画
- 2. 二分插入排序(Binary Insertion Sort)
- 2.1 简介
- 2.2 二分插入排序步骤
- 2.3 二分插入排序C语言实现
- 2.4 二分插入排序的时间复杂度
- 2.5 二分插入排序的时间复杂度
1.插入排序(Insertion Sort)
1.1 简介
插入排序(Insertion Sort)是一种简单直观的排序算法,它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。插入排序在实现上,通常采用in-place排序(即只需用到O(1)的额外空间的排序),因而在从后向前扫描过程中,找到合适位置并插入。
插入排序(Insertion Sort)是一种简单直观的排序算法,它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。插入排序在实现上,通常采用in-place排序(即只需用到O(1)的额外空间的排序),因而在从后向前扫描过程中,找到合适位置并插入。
1.2 插入排序的步骤
- 初始状态:假设第一个元素已经排序(即长度为1的数组是有序的)。
- 遍历未排序部分:从第二个元素开始,依次取出每一个元素。
- 插入元素:
- 将已取出的元素(记为key)与已排序部分的元素从后向前比较。
- 如果已排序部分的元素大于key,则将该元素向后移动一位。
- 重复上述步骤,直到找到key的合适位置,将其插入。
- 重复:重复步骤2和3,直到所有元素均已排序。
1.3 插入排序的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;// 将arr[i]插入到已排序的arr[0..i-1]部分while (j >= 0 && arr[j] > key) {arr[j + 1] = arr[j];j = j - 1;}arr[j + 1] = key;}
}// 打印数组函数
void printArray(int arr[], int size) {int i;for (i = 0; i < size; i++)printf("%d ", arr[i]);printf("\n");
}// 主函数
int main() {int arr[] = {12, 11, 13, 5, 6};int n = sizeof(arr) / sizeof(arr[0]);printf("排序前的数组: \n");printArray(arr, n);insertionSort(arr, n);printf("排序后的数组: \n");printArray(arr, n);return 0;
}
1.4 插入排序的时间复杂度
- 最佳情况:O(n)(数组已经是有序的)
- 最坏情况:O(n2)(数组是逆序的)
- 平均情况:O(n2)
1.5 插入排序的空间复杂度
- 插入排序是in-place排序算法,因此其空间复杂度为O(1)。
1.6 插入排序的动画

2. 二分插入排序(Binary Insertion Sort)
2.1 简介
它通过引入二分查找(Binary Search)算法来优化查找插入位置的过程。在标准的插入排序中,为了将当前元素插入到已排序部分的正确位置,算法需要从后向前扫描已排序部分,直到找到比当前元素大的第一个元素或到达数组的开头。
2.2 二分插入排序步骤
- 从数组的第二个元素开始,将每个元素视为待插入元素。
- 使用二分查找算法在已排序部分中查找待插入元素的正确位置。
- 将已排序部分中大于待插入元素的元素向后移动一位,以腾出空间。
- 将待插入元素插入到正确位置。
- 重复步骤1-4,直到数组完全排序。
2.3 二分插入排序C语言实现
#include <stdio.h>// 二分查找函数,返回插入位置的前一个索引
int binarySearch(int arr[], int item, int low, int high) {if (high <= low)return (item > arr[low]) ? (low + 1) : low;int mid = (low + high) / 2;if (item == arr[mid])return mid + 1;if (item > arr[mid])return binarySearch(arr, item, mid + 1, high);return binarySearch(arr, item, low, mid - 1);
}// 二分插入排序函数
void binaryInsertionSort(int arr[], int n) {int i, j, key, loc;for (i = 1; i < n; i++) {key = arr[i];// 使用二分查找找到插入位置loc = binarySearch(arr, key, 0, i - 1);// 移动元素以腾出空间for (j = i - 1; j >= loc; j--) {arr[j + 1] = arr[j];}arr[loc] = key;}
}// 打印数组函数
void printArray(int arr[], int size) {int i;for (i = 0; i < size; i++)printf("%d ", arr[i]);printf("\n");
}// 主函数
int main() {int arr[] = {37, 23, 0, 17, 12, 72, 31, 46, 100, 88, 54};int n = sizeof(arr) / sizeof(arr[0]);printf("排序前的数组: \n");printArray(arr, n);binaryInsertionSort(arr, n);printf("排序后的数组: \n");printArray(arr, n);return 0;
}
二分插入排序的时间和空间复杂度分析如下:
2.4 二分插入排序的时间复杂度
二分插入排序的时间复杂度主要由两部分组成:二分查找和元素移动。
- 二分查找:在每次插入时,使用二分查找来确定插入位置。二分查找的时间复杂度是对数级别的,即O(log n),其中n是已排序部分的长度。然而,需要注意的是,这里的n并不是整个数组的长度,而是已排序部分的长度。在插入排序的过程中,已排序部分的长度是逐渐增加的。
- 元素移动:当找到插入位置后,需要将该位置及其之后的元素向后移动一位,以腾出空间插入新元素。这个过程的时间复杂度是线性的,即O(n),其中n是已排序部分的长度(在插入当前元素之前的长度)。在最坏情况下,当前元素可能需要被插入到已排序部分的开头,导致所有已排序的元素都需要向后移动一位。
由于二分插入排序在每次插入时都需要进行二分查找和元素移动,因此其总体时间复杂度仍然是O(n2)。这是因为,虽然二分查找减少了比较次数,但元素移动的次数并没有减少。在插入n个元素的过程中,每个元素都可能需要进行O(n)次的移动(在最坏情况下),因此总的时间复杂度是O(n2)。
2.5 二分插入排序的时间复杂度
二分插入排序是就地排序算法(in-place sorting algorithm),它不需要额外的存储空间来存储中间结果。算法在排序过程中只需要几个额外的变量来存储临时值和索引,因此其空间复杂度是O(1)。
综上所述,二分插入排序的时间复杂度是O(n2),空间复杂度是O(1)。这些复杂度特性使得二分插入排序在处理小规模数据集或几乎已排序的数据集时可能表现出较好的性能,但在处理大规模数据集时则不是最优选择。
相关文章:
排序算法 -插入排序
文章目录 1.插入排序(Insertion Sort)1.1 简介1.2 插入排序的步骤1.3 插入排序的C实现1.4 插入排序的时间复杂度1.5 插入排序的空间复杂度1.6 插入排序的动画 2. 二分插入排序(Binary Insertion Sort)2.1 简介2.2 二分插入排序步骤…...
如何使用.bat实现电脑自动重启?
1、在电脑桌面新建一个记事本文档,将如下内容写进去: echo off shutdown /r /t 02、然后,保存一下,再把桌面此文件重命名为电脑重启.bat 3、双击此程序,可以立刻重启电脑。 PS:① 此程序会不保存任何当前…...
使用VSCode远程连接服务器并解决Neo4j无法登陆问题
摘要:本文介绍了如何通过VSCode连接内网部署的Neo4j服务器,并启动服务。在访问Neo4j登录界面时,遇到了端口映射问题导致无法登录。通过手动添加7687端口的映射后,成功登录Neo4j。 我在内网部署了一台服务器,并在其上运…...
使用React和Vite构建一个AirBnb Experiences克隆网站
这一篇文章中,我会教你如何做一个AirBnb Experiences的克隆网站。主要涵盖React中Props的使用。 克隆网站最终呈现的效果: 1. 使用vite构建基础框架 npm create vitelatestcd airbnb-project npm install npm run dev2. 构建网站的3个部分 网站从上…...
HBase压测 ycsb
## ycsb 导入数据 rootXX.14.40.1971、对portrait压测 ansible hadoop -i hosts_hbase_portrait_20230730.txt -m shell -a "hostname && chdir/data/workspace/ycsb-0.17.0 nohup bin/ycsb load hbase20 -P workloads/workload_insert -cp /usr/local/fqlhadoop/…...
基于Python+Django+Vue3+MySQL实现的前后端分类的商场车辆管理系统
项目名称:基于PythonDjangoVue3MySQL实现的前后端分离商场车辆管理系统 技术栈 开发工具:PyCharm、Visual Studio Code (VSCode)运行环境:Python 3.10、MySQL 8.0、Node.js 18技术框架:Django 5、Vue 3.4、Ant-Design-Vue 4.12 …...
网络安全web基础_HTML基础(扫盲篇)
web基础_HTML扫盲篇 一、什么是 HTML? 二、HTML 的基本特点 三、HTML 基本结构概述 1.文档声明(!DOCTYPE html) 2. html元素 3. head元素 4. body 元素 四、HTML5的主要标签清单 文档结构标签 文本内容标签 链接和锚点标签 表格标…...
(附项目源码)Java开发语言,监督管家APP的设计与实现 58,计算机毕设程序开发+文案(LW+PPT)
摘要 随着互联网的快速发展和智能手机的普及,越来越多的用户选择通过移动应用程序进行事项设定、提醒通知和事项打卡。监督管家APP作为一个专注于事项设定、提醒通知、事项打卡的监督管理平台,具有广泛的应用前景和商业价值。本研究旨在构建一个功能丰富…...
前端基础的讲解-JS(11)
对象 对象是什么? 在 JavaScript 中,对象是一组无序的相关属性和方法的集合,所有的事物都是对象,所有的数据类型都可以存放在内。 属性:即事物的特征,在对象中用属性来表示(常用名词…...
Python魔法方法深度解析:解密__call__、__new__和__del__的核心奥义
解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界 《Python OpenCV从菜鸟到高手》带你进入图像处理与计算机视觉的大门! Python中的魔法方法(Magic Methods)是构建Python高级功能的基础,它们使得对象可以…...
当微软windows的记事本被AI加持
1985年,微软发布了Windows 1.0,推出了一款革命性的产品:记事本(Notepad)。这款软件旨在鼓励使用一种未来主义的新设备——鼠标,并让人们可以不依赖VI等键盘工具就能书写文本和编写代码。记事本因其简洁和高…...
Python酷库之旅-第三方库Pandas(213)
目录 一、用法精讲 996、pandas.DatetimeIndex.day属性 996-1、语法 996-2、参数 996-3、功能 996-4、返回值 996-5、说明 996-6、用法 996-6-1、数据准备 996-6-2、代码示例 996-6-3、结果输出 997、pandas.DatetimeIndex.hour属性 997-1、语法 997-2、参数 99…...
普林斯顿:LLM基于边际优化的梯度纠缠
📖标题:A Common Pitfall of Margin-based Language Model Alignment: Gradient Entanglement 🌐来源:arXiv, 2410.13828 🌟摘要 🔸从人类反馈中强化学习(RLHF)已成为对齐语言模型…...
通俗易懂:什么是 Java 类加载?
文章目录 类加载过程的三个阶段一个简单的案例:类加载的工作原理使用这个类类加载的顺序类加载的特点类加载的好处总结推荐阅读文章 在 Java 中, 类加载是一种将我们写的 Java 类文件加载到内存中的过程,让 JVM(Java 虚拟机&…...
Dijkstra 算法的实现方案
下面是一个基于 Dijkstra 算法的实现方案,能够在 DEM(数字高程模型)数据上进行寻路,并满足以下需求: 使用 Qt C++ 编写; 规避 DEM 中的障碍物; 支持指定起点和终点; 使用 GDAL 库读取 DEM 文件; 输出路径到 TXT 文件; 输出的坐标为地理坐标(例如经纬度),而不是像…...
OpenGL 进阶系列07 - 阴影贴图(shadowmap )
一:概述: 在 OpenGL 中,Shadow Mapping(阴影贴图)是一种常用的实时阴影技术,用于渲染物体的阴影效果。这种方法通过生成光源视角下的深度贴图,再在场景渲染时使用它来判断物体是否被遮挡,从而实现阴影效果。下面是实现 Shadow Mapping 的基本步骤和相关知识。 二:绘制…...
【CAN介绍】【第一篇章】
1. CAN简介 • CAN 总线( Controller Area Network Bus )控制器局域网总线 • CAN 总线是由 BOSCH 公司开发的一种简洁易用、传输速度快、易扩展、可靠性高的串行通信总线,广泛应用于汽车、嵌入式、工业控制等领域 • CAN 总线特征࿱…...
【统计子矩阵——部分前缀和+双指针】
题目 代码 #include <bits/stdc.h> using namespace std; typedef long long ll; const int N 510; int s[N][N]; int main() {ios::sync_with_stdio(0);cin.tie(0);int n, m, k;cin >> n >> m >> k;for(int i 1; i < n; i)for(int j 1; j <…...
用正则表达式检查是IP否为内网地址
用正则表达式检查是ip否为内网地址 PHP function isIntranet($ip) {/* IPV4内网地址A 类10.0.0.0~10.255.255.255B 类172.16.0.0~172.31.255.255C 类192.168.0.0~192.168.255.255*/// 检查是否为 IPv4 内网地址if (preg_match(/^10\./, $ip…...
Leetcode刷题笔记14
136. 只出现一次的数字 136. 只出现一次的数字 - 力扣(LeetCode) 核心思想:按位异或运算 利用按位异或运算的性质来解决这个问题: 异或运算的性质: a ^ a 0:相同的数异或结果为0。 a ^ 0 a:…...
Docker 离线安装指南
参考文章 1、确认操作系统类型及内核版本 Docker依赖于Linux内核的一些特性,不同版本的Docker对内核版本有不同要求。例如,Docker 17.06及之后的版本通常需要Linux内核3.10及以上版本,Docker17.09及更高版本对应Linux内核4.9.x及更高版本。…...
Leetcode 3576. Transform Array to All Equal Elements
Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接:3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到…...
React hook之useRef
React useRef 详解 useRef 是 React 提供的一个 Hook,用于在函数组件中创建可变的引用对象。它在 React 开发中有多种重要用途,下面我将全面详细地介绍它的特性和用法。 基本概念 1. 创建 ref const refContainer useRef(initialValue);initialValu…...
Spring AI 入门:Java 开发者的生成式 AI 实践之路
一、Spring AI 简介 在人工智能技术快速迭代的今天,Spring AI 作为 Spring 生态系统的新生力量,正在成为 Java 开发者拥抱生成式 AI 的最佳选择。该框架通过模块化设计实现了与主流 AI 服务(如 OpenAI、Anthropic)的无缝对接&…...
企业如何增强终端安全?
在数字化转型加速的今天,企业的业务运行越来越依赖于终端设备。从员工的笔记本电脑、智能手机,到工厂里的物联网设备、智能传感器,这些终端构成了企业与外部世界连接的 “神经末梢”。然而,随着远程办公的常态化和设备接入的爆炸式…...
HashMap中的put方法执行流程(流程图)
1 put操作整体流程 HashMap 的 put 操作是其最核心的功能之一。在 JDK 1.8 及以后版本中,其主要逻辑封装在 putVal 这个内部方法中。整个过程大致如下: 初始判断与哈希计算: 首先,putVal 方法会检查当前的 table(也就…...
比较数据迁移后MySQL数据库和OceanBase数据仓库中的表
设计一个MySQL数据库和OceanBase数据仓库的表数据比较的详细程序流程,两张表是相同的结构,都有整型主键id字段,需要每次从数据库分批取得2000条数据,用于比较,比较操作的同时可以再取2000条数据,等上一次比较完成之后,开始比较,直到比较完所有的数据。比较操作需要比较…...
如何应对敏捷转型中的团队阻力
应对敏捷转型中的团队阻力需要明确沟通敏捷转型目的、提升团队参与感、提供充分的培训与支持、逐步推进敏捷实践、建立清晰的奖励和反馈机制。其中,明确沟通敏捷转型目的尤为关键,团队成员只有清晰理解转型背后的原因和利益,才能降低对变化的…...
Spring Boot + MyBatis 集成支付宝支付流程
Spring Boot MyBatis 集成支付宝支付流程 核心流程 商户系统生成订单调用支付宝创建预支付订单用户跳转支付宝完成支付支付宝异步通知支付结果商户处理支付结果更新订单状态支付宝同步跳转回商户页面 代码实现示例(电脑网站支付) 1. 添加依赖 <!…...
麒麟系统使用-进行.NET开发
文章目录 前言一、搭建dotnet环境1.获取相关资源2.配置dotnet 二、使用dotnet三、其他说明总结 前言 麒麟系统的内核是基于linux的,如果需要进行.NET开发,则需要安装特定的应用。由于NET Framework 是仅适用于 Windows 版本的 .NET,所以要进…...
