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

归并排序和快速排序的两种实现

在此之前我们已经介绍过归并排序和快速排序:浅谈归并排序与快速排序,但其中的实现都是基于递归的。本文将重新温故这两种算法并给出基于迭代的实现。

目录

  • 1. 归并排序
    • 1.1 基于递归
    • 1.2 基于迭代
  • 2. 快速排序
    • 2.1 基于递归
    • 2.2 基于迭代

1. 归并排序

1.1 基于递归

归并排序的核心是二路归并,实现二路归并需要一个额外的辅助数组,因此空间复杂度是 O ( n ) O(n) O(n)

void merge(vector<int>& a, int l, int mid, int r, vector<int>& tmp) {int i = l, j = mid + 1, k = l;while (i <= mid && j <= r) {if (a[i] <= a[j]) tmp[k++] = a[i++];else tmp[k++] = a[j++];}while (i <= mid) tmp[k++] = a[i++];while (j <= r) tmp[k++] = a[j++];for (int i = l; i <= r; i++) a[i] = tmp[i];
}

该函数会对数组 a[l, mid][mid + 1, r] 两部分进行二路归并,其中辅助数组 tmp 的大小与 a 相同。

有了 merge 函数,我们就可以很方便的实现归并排序了:

void merge_sort(vector<int>& a, int l, int r, vector<int>& tmp) {if (l >= r) return;int mid = l + r >> 1;merge_sort(a, l, mid, tmp), merge_sort(a, mid + 1, r, tmp);merge(a, l, mid, r, tmp);
}

1.2 基于迭代

很明显,基于递归的实现是自顶向下的,而基于迭代的实现是自底向上的。

我们可以先枚举区间长度,再枚举区间左端点。一开始每个区间的长度是 1 1 1,我们每次对相邻的两个区间进行二路归并,每归并一次区间的长度就是原先的两倍,所以枚举区间长度时变量 len 的更新方式为 len *= 2

对于区间左端点,每合并完两个区间后,左端点就要更新成下下个区间,如下图所示:

还需保证 mid < n - 1,即 l < n - len

void merge_sort(vector<int>& a) {int n = a.size();vector<int> tmp(n);for (int len = 1; len < n; len *= 2) {for (int l = 0; l < n - len; l += 2 * len) {int mid = l + len - 1;int r = min(l + 2 * len - 1, n - 1);merge(a, l, mid, r, tmp);}}
}

归并排序的时间复杂度是 O ( n log ⁡ n ) O(n\log n) O(nlogn),无论是递归还是迭代,空间复杂度都是 O ( n ) O(n) O(n)

2. 快速排序

2.1 基于递归

void quick_sort(vector<int>& a, int l, int r) {if (l >= r) return;int mid = l + r >> 1;int i = l - 1, j = r + 1, x = a[mid];while (i < j) {while (a[++i] < x);while (a[--j] > x);if (i < j) swap(a[i], a[j]);}quick_sort(a, l, j), quick_sort(a, j + 1, r);
}

2.2 基于迭代

void quick_sort(vector<int>& a, int l, int r) {if (l >= r) return;stack<pair<int, int>> stk;stk.emplace(l, r);while (!stk.empty()) {auto [l, r] = stk.top();stk.pop();if (l < r) {int mid = l + r >> 1;int i = l - 1, j = r + 1, x = a[mid];while (i < j) {while (a[++i] < x);while (a[--j] > x);if (i < j) swap(a[i], a[j]);}stk.emplace(l, j);stk.emplace(j + 1, r);}}
}

时间复杂度是 O ( n log ⁡ n ) O(n\log n) O(nlogn),空间复杂度是 O ( log ⁡ n ) O(\log n) O(logn)

相关文章:

归并排序和快速排序的两种实现

在此之前我们已经介绍过归并排序和快速排序&#xff1a;浅谈归并排序与快速排序&#xff0c;但其中的实现都是基于递归的。本文将重新温故这两种算法并给出基于迭代的实现。 目录 1. 归并排序1.1 基于递归1.2 基于迭代 2. 快速排序2.1 基于递归2.2 基于迭代 1. 归并排序 1.1 基…...

C#,《小白学程序》第十四课:随机数(Random)第一,几种随机数的计算方法与代码

1 文本格式 /// <summary> /// 《小白学程序》第十四课&#xff1a;随机数&#xff08;Random&#xff09;第一&#xff0c;几种随机数的计算方法与代码 /// 本课初步接触一下随机数。 /// </summary> /// <param name"sender"></param> ///…...

[杂谈]-快速了解Modbus协议

快速了解Modbus协议 文章目录 快速了解Modbus协议1、为何 Modbus 如此受欢迎2、范围和数据速率3、逻辑电平4、层数5、网络与通讯6、数据帧格式7、数据类型8、服务器如何存储数据9、总结 ​ Modbus 是一种流行的低速串行通信协议&#xff0c;广泛应用于自动化行业。 该协议由 Mo…...

WhatsApp的两个商业模式该如何选择

WhatsApp Business 是什么 目前 WhatsApp 提供两种商业模式&#xff0c;企业应根据自身需求选择相应版本。 第一个版本是 WhatsApp Business&#xff1a;初创企业只需一个手机应用程序&#xff0c;便可以个体单位与客户轻松互动; 另一个版本是 WhatsApp Business API&#xff…...

动态表单设计

动态表单设计 背景方案讨论基于上面分析&#xff0c;对比调研&#xff0c;自定义动态表单数据模型表单详解&#xff08;一&#xff09; 表单模板&#xff1a;jim_dynamic_form&#xff08;二&#xff09;表单数据类型&#xff1a;jim_form_data_type&#xff08;三&#xff09;…...

JAR will be empty - no content was marked for inclusion!

现象 在对自建pom依赖组件打包时&#xff0c;出现JAR will be empty - no content was marked for inclusion!错误。 方案 在pom中怎么加packaging标签内容为pom&#xff0c;标识只打包pom文件 <?xml version"1.0" encoding"UTF-8"?> ...<grou…...

软件生命周期及流程【软件测试】

软件的生命周期 软件生命周期是软件开始研制到最终被废弃不用所经历的各个阶段。 瀑布型生命周期模型 规定了它们自上而下、相互衔接的固定次序&#xff0c;如同瀑布流水&#xff0c;逐级下落&#xff0c;具有顺序性和依赖性。每个阶段规定文档并需进行评审。 特点&#xff…...

2023高教社杯数学建模E题思路代码 - 黄河水沙监测数据分析

# 1 赛题 E 题 黄河水沙监测数据分析 黄河是中华民族的母亲河。研究黄河水沙通量的变化规律对沿黄流域的环境治理、气候变 化和人民生活的影响&#xff0c; 以及对优化黄河流域水资源分配、协调人地关系、调水调沙、防洪减灾 等方面都具有重要的理论指导意义。 附件 1 给出了位…...

双翌保养码使用指南方法(一)

保养码使用指南一 为了确保软件的正常运行和有效使用&#xff0c;正确地使用保养码是至关重要的。以下是保养码使用的简单指南&#xff0c;以帮助您进行正确的操作。 1. 打开软件入口&#xff1a;首先&#xff0c;在您的电脑上打开文件夹&#xff0c;并找到s-y softactive tool…...

hive指定字段插入数据,包含了分区表和非分区表

1、建表 语句如下&#xff1a; CREATE EXTERNAL TABLE ods_lineitem_full (l_shipdate date,l_orderkey bigint,l_linenumber int,l_partkey int,l_suppkey int,l_quantity decimal(15, 2),l_extendedprice decimal(15, 2),l_discount de…...

浏览器端vscode docker搭建(附带python环境)

dockerfile from centos:7 #安装python环境 run yum -y install wget openssl-devel bzip2-devel expat-devel gdbm-devel readline-devel zlib-devel libffi-devel gcc make run wget https://www.python.org/ftp/python/3.9.0/Python-3.9.0.tgz run tar -xvf Python-3.9.…...

Echarts图表跟随父容器的变化自适应

如果页面中有多个图表 隐藏/展开左边侧边栏echarts图表自适应 <div class"line"><div class"title">制冷站关键参数</div><div id"chartLine1" style"width: 100%;height:85%;"></div></div><…...

【多线程】ThreadLocal是什么?有哪些使用场景?使用ThreadLocal需要注意些什么?

文章目录 前言一、ThreadLocal 是什么&#xff1f;二、有哪些使用场景&#xff1f;三、实现原理四、在线程池中使用 ThreadLocal 为什么可能导致内存泄露呢&#xff1f;五、线程池中&#xff0c;如何正确使用 ThreadLocal&#xff1f;六、ThreadLocal 核心方法 前言 一、Threa…...

一种基于动态代理的通用研发提效解决方案

作为一名研发人员&#xff0c;除了业务开发之外&#xff0c;研发提效是一个永恒的话题&#xff0c;而女娲正是这一话题下进行的一次全面的剖析和实践。 作者&#xff1a;张全洪(钝悟) 一、女娲是什么 女娲是业务研发同学&#xff08;开发、测试、运维&#xff09;在软件迭代的…...

【vue3】一些关于hooks的使用经验

前言 最近接到了一个需求&#xff0c;隔壁嵌入式部门希望我们用前端解析渲染Kconfig表单。这篇文章用来记录一下本次使用hook pinia vue3的经验 hooks hooks的概念最早是在 React 中听到的&#xff0c;虽然早些时间也写过一点react&#xff0c;但也只是照葫芦画瓢&#xf…...

面试系列 - Java 并发容器详解

Java 并发容器是一组用于在多线程环境下安全访问和操作数据的数据结构。它们提供了线程安全的集合和映射&#xff0c;使开发者能够更轻松地处理并发编程问题。 一、Java并发容器 ConcurrentHashMap&#xff1a; 它是一个高效的并发哈希表&#xff0c;支持多线程并发操作而不需…...

使用动态住宅代理还能带来哪些好处?

一、什么是动态住宅代理ip 动态住宅代理是一种代理技术&#xff0c;它利用代理服务器中转用户和目标服务器之间的网络流量&#xff0c;实现用户真实位置的屏蔽。代理提供商会有自己的ip大池子&#xff0c;当你通过代理服务器向网站发送请求时&#xff0c;服务器会从池子中选中…...

笙默考试管理系统-MyExamTest----codemirror(18)

笙默考试管理系统-MyExamTest----codemirror&#xff08;18&#xff09; 目录 一、 笙默考试管理系统-MyExamTest----codemirror 二、 笙默考试管理系统-MyExamTest----codemirror 三、 笙默考试管理系统-MyExamTest----codemirror 四、 笙默考试管理系统-MyExamTest---…...

TGA格式文件转材质

今天淘宝上买了一个美女的模型&#xff0c;是blender的源文件&#xff0c;上面说有fbx格式的。我用unity&#xff0c;所以觉得应该可以用。文件内容如下图&#xff1a; FBX文件夹打开后&#xff0c;内容如下图所示&#xff0c;当时就预感到可能没有色彩。 unity打开后果然发现只…...

IP应用场景查询API:深入了解网络用户行为的利器

前言 随着数字时代的不断发展&#xff0c;互联网已经成为人们生活的重要组成部分。而随着越来越多的业务和社交活动迁移到在线平台上&#xff0c;了解和理解网络用户行为变得至关重要。为了满足这个需求&#xff0c;IP 应用场景查询 API 崭露头角&#xff0c;成为深入了解网络…...

Linux应用开发之网络套接字编程(实例篇)

服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …...

AI-调查研究-01-正念冥想有用吗?对健康的影响及科学指南

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; &#x1f680; AI篇持续更新中&#xff01;&#xff08;长期更新&#xff09; 目前2025年06月05日更新到&#xff1a; AI炼丹日志-28 - Aud…...

Prompt Tuning、P-Tuning、Prefix Tuning的区别

一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...

【Zephyr 系列 10】实战项目:打造一个蓝牙传感器终端 + 网关系统(完整架构与全栈实现)

🧠关键词:Zephyr、BLE、终端、网关、广播、连接、传感器、数据采集、低功耗、系统集成 📌目标读者:希望基于 Zephyr 构建 BLE 系统架构、实现终端与网关协作、具备产品交付能力的开发者 📊篇幅字数:约 5200 字 ✨ 项目总览 在物联网实际项目中,**“终端 + 网关”**是…...

Linux-07 ubuntu 的 chrome 启动不了

文章目录 问题原因解决步骤一、卸载旧版chrome二、重新安装chorme三、启动不了&#xff0c;报错如下四、启动不了&#xff0c;解决如下 总结 问题原因 在应用中可以看到chrome&#xff0c;但是打不开(说明&#xff1a;原来的ubuntu系统出问题了&#xff0c;这个是备用的硬盘&a…...

前端开发面试题总结-JavaScript篇(一)

文章目录 JavaScript高频问答一、作用域与闭包1.什么是闭包&#xff08;Closure&#xff09;&#xff1f;闭包有什么应用场景和潜在问题&#xff1f;2.解释 JavaScript 的作用域链&#xff08;Scope Chain&#xff09; 二、原型与继承3.原型链是什么&#xff1f;如何实现继承&a…...

管理学院权限管理系统开发总结

文章目录 &#x1f393; 管理学院权限管理系统开发总结 - 现代化Web应用实践之路&#x1f4dd; 项目概述&#x1f3d7;️ 技术架构设计后端技术栈前端技术栈 &#x1f4a1; 核心功能特性1. 用户管理模块2. 权限管理系统3. 统计报表功能4. 用户体验优化 &#x1f5c4;️ 数据库设…...

Java求职者面试指南:计算机基础与源码原理深度解析

Java求职者面试指南&#xff1a;计算机基础与源码原理深度解析 第一轮提问&#xff1a;基础概念问题 1. 请解释什么是进程和线程的区别&#xff1f; 面试官&#xff1a;进程是程序的一次执行过程&#xff0c;是系统进行资源分配和调度的基本单位&#xff1b;而线程是进程中的…...

Python+ZeroMQ实战:智能车辆状态监控与模拟模式自动切换

目录 关键点 技术实现1 技术实现2 摘要&#xff1a; 本文将介绍如何利用Python和ZeroMQ消息队列构建一个智能车辆状态监控系统。系统能够根据时间策略自动切换驾驶模式&#xff08;自动驾驶、人工驾驶、远程驾驶、主动安全&#xff09;&#xff0c;并通过实时消息推送更新车…...

群晖NAS如何在虚拟机创建飞牛NAS

套件中心下载安装Virtual Machine Manager 创建虚拟机 配置虚拟机 飞牛官网下载 https://iso.liveupdate.fnnas.com/x86_64/trim/fnos-0.9.2-863.iso 群晖NAS如何在虚拟机创建飞牛NAS - 个人信息分享...