排序算法 -插入排序
文章目录
- 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:…...

PHP图书绘本借阅管理系统小程序源码
📚 图书绘本借阅管理系统:打造孩子的阅读乐园 📚 🏷️ 引言:为什么我们需要图书绘本借阅管理系统? 在孩子的成长旅程中,阅读是不可或缺的一部分。然而,面对琳琅满目的图书和绘本&a…...

【JavaWeb】JavaWeb入门之XML详解
目录 1.XML介绍 1.1.XML概述 1.1.1.什么是XML 1.1.2.XML的作用 1.1.3.XML与HTML的比较 1.1.4.XML和properties(属性文件)比较 1.1.5.W3C组织 1.2.XML语法概述 1.2.1.XML文档展示 1.2.2.XML文档的组成部分 1.3.XML文档声明 1.3.1.什么是XML文…...

JS手写-this绑定实现
在 JavaScript 中,bind、call 和 apply 方法都可以用来改变函数的 this 指向。下面我们将分别实现这些方法的简单版本。 1. 实现 bind bind 方法创建一个新的函数,在调用时设置 this 值,并返回这个新的函数。 Function.prototype.myBind …...

【时间之外】IT人求职和创业应知【31】
目录 新闻一:2024年“秦创原沣东杯”陕西省科技工作者创新创业大赛颁奖仪式暨沣东新城机器人产业发展大会盛大启幕 新闻二:声网CEO赵斌:RTE将成为生成式AI时代AI Infra的关键部分 新闻三:“5G工业互联网”融合应用试点城市名单…...

如何使用ffmpeg命令行进行录屏
录屏软件,我们去网上下载,发现有很多软件都是要收费的!但是录屏功能很难做吗?为啥都需要收费呢? 于是我整了个小demo,用于实现基础的屏幕录制功能。 思路很简单,考虑到 FFMpeg.exe是一个非常成…...

ODOO学习笔记(8):模块化架构的优势
灵活性与可定制性 业务流程适配:企业的业务流程往往因行业、规模和管理方式等因素而各不相同。Odoo的模块化架构允许企业根据自身的具体业务流程,选择和组合不同的模块。例如,一家制造企业可以启用采购、库存、生产和销售模块,并通…...

数字IC后端实现之Innovus specifyCellEdgeSpacing和ICC2 set_placement_spacing_rule的应用
昨天帮助社区IC训练营学员远程协助解决一个Calibre DRC案例。通过这个DRC Violation向大家分享下Innovus和ICC2中如何批量约束cell的spacing rule。 数字IC后端手把手实战教程 | Innovus verify_drc VIA1 DRC Violation解析及脚本自动化修复方案 下图所示为T12nm A55项目的Ca…...

每日小练:Day2
1.乒乓球筐 题目链接:乒乓球筐__牛客网 题目描述: 这道题主要考察B盒是不是A盒的子集,我们可以通过哈希表来做 单哈希表 import java.util.Scanner;// 注意类名必须为 Main, 不要有任何 package xxx 信息 public class Main {public stat…...

ubuntu 安装kafka-eagle
上传压缩包 kafka-eagle-bin-2.0.8.tar.gz 到集群 /root/efak 目录 cd /root/efak tar -zxvf kafka-eagle-bin-2.0.8.tar.gz cd /root/efak/kafka-eagle-bin-2.0.8 mkdir /root/efakmodule tar -zxvf efak-web-2.0.8-bin.tar.gz -C /root/efakmodule/ mv /root/efakmodule/efak…...

深入理解指针
在初步了解了指针的用法之后,我们可以想一想,既然一个变量有地址,而且在上一篇文章中我们知道了一个数组也有地址,那么函数、字符串这些东西有没有地址呢?如果有,那这些地址有什么用?我们又要怎…...