时间复杂度为 O(n^2) 的排序算法

大家好,我是 方圆。对于小规模数据,我们可以选用时间复杂度为 O(n2) 的排序算法,因为时间复杂度并不代表实际代码的执行时间,而且它也省去了低阶、系数和常数,仅代表的增长趋势,所以在小规模数据情况下, O(n2) 的排序算法可能会比 O(nlogn) 的排序算法执行效率高。不过随着数据规模增大, O(nlogn) 的排序算法是不二选择。本篇我们主要对 O(n2) 的排序算法进行介绍,在介绍之前,我们先了解一下算法特性:

  • 算法特性:

    • 稳定性:经排序后,若等值元素之间的相对位置不变则为稳定排序算法,否则为不稳定排序算法

    • 原地排序:是否借助额外辅助空间

    • 自适应性: 自适应性排序受输入数据的影响,即最佳/平均/最差时间复杂度不等,而非自适应排序时间复杂度恒定

本篇我们将着重介绍插入排序,选择排序和冒泡排序了解即可。

插入排序

插入排序的工作方式像 整理手中的扑克牌一样,即不断地将每一张牌插入到其他已经有序的牌中适当的位置。

插入排序的当前索引元素左侧的所有元素都是有序的:若当前索引为 i,则 [0, i - 1] 区间内的元素始终有序,这种性质被称为 循环不变式,即在第一次迭代、迭代过程中和迭代结束时,这种性质始终保持不变。

不过,这些有序元素的索引位置暂时不能确定,因为它们可能需要为更小的元素腾出空间而向右移动。插入排序的代码实现如下:

    private void sort(int[] nums) {for (int i = 1; i < nums.length; i++) {int base = nums[i];int j = i - 1;while (j >= 0 && nums[j] > base) {nums[j + 1] = nums[j--];}nums[j + 1] = base;}}

它的实现逻辑是取未排序区间中的某个元素为基准数 base,将 base 与其左侧已排序区间元素依次比较大小,并"插入"到正确位置。插入排序对 部分有序(数组中每个元素距离它的最终位置都不远或数组中只有几个元素的位置不正确等情况)的数组排序效率很高。事实上,当逆序很少或数据量不大(n2和nlogn比较接近)时,插入排序可能比其他任何排序算法都要快,这也是一些编程语言的内置排序算法在针对小数据量数据排序时选择使用插入排序的原因。

算法特性:

  • 空间复杂度:O(1)

  • 原地排序

  • 稳定排序

  • 自适应排序:当数组为升序时,时间复杂度为 O(n);当数组为降序时,时间复杂度为 O(n2)

希尔排序

插入排序对于大规模乱序数组排序很慢,因为它只会交换相邻的元素,所以元素只能一步步地从一端移动到另一端,如果最小的元素恰好在数组的最右端,要将它移动到正确的位置需要移动 N - 1 次。

希尔排序是基于插入排序改进的排序算法,它可以交换不相邻的元素以对数组的局部进行排序,并最终用插入排序将局部有序的数组排序。它的思想是使数组中间隔为 h 的元素有序(h 有序数组),如下图为间隔为 4 的有序数组:

希尔排序.jpg

排序之初 h 较大,这样我们能将较小的元素尽可能移动到靠近左端的位置,为实现更小的 h 有序创造便利,最后一次循环时 h 为 1,便是我们熟悉的插入排序。这就是希尔排序的过程,代码实现如下:

    private void sort(int[] nums) {int N = nums.length;int h = 1;while (h < N / 3) {h = 3 * h + 1;}while (h >= 1) {for (int i = h; i < N; i++) {int base = nums[i];int j = i - h;while (j >= 0 && nums[j] > base) {nums[j + h] = nums[j];j -= h;}nums[j + h] = base;}h /= 3;}}

希尔排序更高效的原因是它权衡了子数组的规模和有序性,它也可以用于大型数组。排序之初,各个子数组都很短,排序之后子数组都是部分有序的,这两种情况都很适合插入排序。


选择排序

选择排序的实现非常简单:每次选择未排序数组中的最小值,将其放到已排序区间的末尾,代码实现如下:

    private void sort(int[] nums) {for (int i = 0; i < nums.length; i++) {int min = i;for (int j = i + 1; j < nums.length; j++) {if (nums[j] < nums[min]) {min = j;}}swap(nums, i, min);}}private void swap(int[] nums, int i, int j) {int temp = nums[i];nums[i] = nums[j];nums[j] = temp;}

算法特性:

  • 空间复杂度:O(1)

  • 原地排序

  • 非稳定排序:会改变等值元素之间的相对位置

  • 非自适应排序:最好/平均/最坏时间复杂度均为 O(n2)

冒泡排序

冒泡排序通过 连续地比较与交换相邻元素实现排序,每轮循环会将未被排序区间内的最大值移动到数组的最右端,这个过程就像是气泡从底部升到顶部一样,代码实现如下:

    public void sort(int[] nums) {for (int i = nums.length - 1; i > 0; i--) {// 没有发生元素交换的标志位boolean flag = true;for (int j = 0; j < i; j++) {if (nums[j] > nums[j + 1]) {swap(nums, j, j + 1);flag = false;}}if (flag) {break;}}}private void swap(int[] nums, int i, int j) {int temp = nums[i];nums[i] = nums[j];nums[j] = temp;}

算法特性:

  • 空间复杂度:O(1)

  • 原地排序

  • 稳定排序

  • 自适应排序:经过优化后最佳时间复杂度为 O(n)


巨人的肩膀

  • 《算法导论 第三版》第 2.1 章

  • 《算法 第四版》第 2.1 章

  • 《Hello 算法》第 11 章

  • 排序算法-希尔排序

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

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

相关文章

PyTorch 深度学习之循环神经网络(基础篇)Basic RNN(十一)

0.Revision: DNN dense 重义层 全连接 RNN处理带有序列的数据 1. What is RNNs? linear layer 1.1 What is RNN? tanh (-1, 1) 1.2 RNN Cell in PyTorch 1.3 How to use RNNCell *先把维度搞清楚 多了一个序列的维度 2. How to use RNN 2.1 How to use RNN - numLayers…

基于变电站自动化系统中的安全措施分析及应用

摘要&#xff1a;阐述变电运行中的问题&#xff0c;电气自动化系统与安全运行措施&#xff0c;包括自动控制设备的投入&#xff0c;电气自动 化与计算机技术相、设备数据的采集与处理、自动化系统的升级、人工智能技术的应用。 关键词&#xff1a;自动控制&#xff1b;数据采…

铜死亡+多组机器学习+WGCNA+分型

今天给同学们分享一篇铜死亡多组机器学习WGCNA分型的生信文章“Machine learning screening for Parkinsons disease-related cuproptosis-related typing development and validation and exploration of personalized drugs for cuproptosis genes”&#xff0c;这篇文章于20…

zabbix内置宏、自动发现与注册

一、zabbix内置宏 1、概念&#xff1a; 在Zabbix中&#xff0c;内置宏是一种特殊的变量&#xff0c;通常用在 Trigger 名称和表达式中&#xff0c;引用有关监控对象的信息。 2、种类&#xff1a; {HOST.NAME} 主机名 {HOST.IP} 主机 IP 地址 {TRIGGER.DESCRIPTION} 触…

Leetcode刷题详解——将x减到0的最小操作数

1. 题目链接&#xff1a;1658. 将 x 减到 0 的最小操作数 2. 题目描述: 给你一个整数数组 nums 和一个整数 x 。每一次操作时&#xff0c;你应当移除数组 nums 最左边或最右边的元素&#xff0c;然后从 x 中减去该元素的值。请注意&#xff0c;需要 修改 数组以供接下来的操作…

017 基于Spring Boot的食堂管理系统

基于Spring Boot的食堂管理系统 项目介绍 本项目是基于Java的管理系统。采用前后端分离开发。前端基于bootstrap框架实现&#xff0c;后端使用Java语言开发&#xff0c;技术栈包括但不限于SpringBoot、MyBatis、MySQL、Maven等&#xff0c;开发工具为IDEA。 功能介绍 主页 …

TX Text Control .NET Server for ASP.NET 32.0 Crack

TX Text Control .NET Server for ASP.NET 是VISUAL STUDIO 2022、ASP.NET CORE .NET 6 和 .NET 7 支持&#xff0c;将文档处理集成到 Web 应用程序中&#xff0c;为您的 ASP.NET Core、ASP.NET 和 Angular 应用程序添加强大的文档处理功能。 客户端用户界面 文档编辑器 将功能…

C语言,指针的一些运算

若创建一个数组&#xff1a;int arr[10] 0; 用指针变量来储存数组首元素的地址&#xff1a;int* p arr,这里arr是数组名&#xff0c;表示首元素地址。 若p p 1或者p之后p本来指向数组首元素地址&#xff0c;就变成了指向第二个元素的地址&#xff0c;p n即指向第n 1个地…

C++对象模型(12)-- 构造函数语义学:构造函数

1、默认构造函数生成规则 编译器不一定会为类生成默认构造函数&#xff0c;但在下列情况下&#xff0c;编译器会生成默认构造函数。 &#xff08;1&#xff09;该类没有任何构造函数&#xff0c;但包含一个类类型的成员变量&#xff0c;且成员变量所属的类有默认构造函数。 …

idea使用debug无法启动,使用run可以启动

1、将调试断点清除 使用快捷键ctrl shift F8&#xff0c;将勾选的选项去除即可 2、Error running SampleApplication: Command line is too long. Shorten command line for SampleApplication or also for Spring Boot default configuration&#xff0c;报这种错误&#x…

uni-app集成使用SQLite

一、打开uni-app中SQLite 二、封装sqlite.js module.exports {dbName: chat, // 数据库名称dbPath: _doc/chat.db, // 数据库地址,推荐以下划线为开头 _doc/xxx.db/*** Description: 创建数据库 或 有该数据库就打开* author: ZXL* createTime: 2023-10-12 09:23:10* Copyr…

SQ4840EY-T1_GE3具有低导通电阻和低电压降 汽车级 N沟道功率MOSFET

SQ4840EY-T1_GE3是一款高性能的车规级电子IC芯片&#xff0c;它具有多种功能和特点&#xff0c;适用于各种电子设备和应用领域。采用了先进的工艺技术&#xff0c;具有高性能和稳定的特点。它采用了先进的封装技术&#xff0c;能够在广泛的温度范围内正常工作&#xff0c;适应各…

【Java基础面试十四】、 封装的目的是什么,为什么要有封装?

文章底部有个人公众号&#xff1a;热爱技术的小郑。主要分享开发知识、学习资料、毕业设计指导等。有兴趣的可以关注一下。为何分享&#xff1f; 踩过的坑没必要让别人在再踩&#xff0c;自己复盘也能加深记忆。利己利人、所谓双赢。 面试官&#xff1a; 封装的目的是什么&…

docker搭建nginx+php-fpm

docker run --name nginx -p 8898:80 -d nginx:1.20.2-alpine# 将容器nginx.conf文件复制到宿主机 docker cp nginx:/etc/nginx/nginx.conf /usr/local/nginx/conf/nginx.conf# 将容器conf.d文件夹下内容复制到宿主机 docker cp nginx:/etc/nginx/conf.d /usr/local/nginx/conf…

【Python-Django】基于TF-IDF算法的医疗推荐系统复现过程

复现步骤 step1&#xff1a; 修改原templates路径&#xff0c;删除&#xff0c;将setting.py中的路径置空 step2&#xff1a; 注册app python manage.py startapp [app名称]在app目录下创建static和templates目录 step3&#xff1a; 将项目中的资源文化进行拷贝 step4&#…

VUE整合Echarts实现简单的数据可视化

文章目录 前言 一、Echarts的安装 二、可视化渲染 1.柱状图 2.饼图 3.主题的下载 总结 前言 ECharts是一款功能强大的前端数据可视化库&#xff0c;支持多种图表类型和统计图表、地理数据可视化、关系型数据展示、多维数据处理和商业智能功能。通过广泛的图表类型、统计分析…

通达OA 2016网络智能办公系统 handle.php SQL注入漏洞

一、漏洞描述 北京通达信科科技有限公司通达OA2016网络智能办公系统 handle.php 存在sql注入漏洞&#xff0c;攻击者可利用此漏洞获取数据库管理员权限&#xff0c;查询数据、获取系统信息&#xff0c;威胁企业单位数据安全。 二、网络空间搜索引擎查询 fofa查询 app"T…

Leetcode刷题解析——最大连续1的个数

1. 题目链接&#xff1a;1004. 最大连续1的个数 III 2. 题目描述&#xff1a; 给定一个二进制数组 nums 和一个整数 k&#xff0c;如果可以翻转最多 k 个 0 &#xff0c;则返回 数组中连续 1 的最大个数 。 示例 1&#xff1a; 输入&#xff1a;nums [1,1,1,0,0,0,1,1,1,1,0]…

6.6 图的应用

思维导图&#xff1a; 6.6.1 最小生成树 ### 6.6 图的应用 #### 主旨&#xff1a;图的概念可应用于现实生活中的许多问题&#xff0c;如网络构建、路径查询、任务排序等。 --- #### 6.6.1 最小生成树 **概念**&#xff1a;要在n个城市中建立通信联络网&#xff0c;则最少需…

【Java 进阶篇】JavaScript 自动跳转首页案例

在这篇博客中&#xff0c;我们将创建一个JavaScript案例&#xff0c;演示如何自动跳转到网站的首页。这种自动跳转通常用于欢迎页面或广告页面等场景。我们将从头开始创建这个案例&#xff0c;逐步介绍相关的JavaScript知识&#xff0c;让初学者也能理解并实现这个功能。 1. 什…