常见的排序算法 【复习笔记】
注意:
1. 后面的排序算法实现都只考虑升序,对于逆序,只有知道原理,实现很容易
2. 案例题:
题目描述:将读入的 N 个数从小到大输出 ( 1 <= N <=10e5)
输入描述:第一行一个正整数 N
第二行 N 个空格隔开的正整数 ai
输出描述:给定的 N 个数从小到大输出,空格隔开,行末换行无空格
输入:5
4 2 4 5 1
输出:1 2 4 4 5
1. 插入排序
1.1 算法思想
每次将一个待排序元素按照关键字大小插入到已排序好的序列中
时间复杂度:1. 当整个序列升序,时间复杂度O(n)
2. 当整个序列逆序,时间复杂度O(N^2)
1.2 代码实现
#include<iostream>
using namespace std;const int N = 1e5 + 10;
int a[N];
int n;void insert_sort()
{//从第二个元素开始,依次枚举待排序元素for (int i = 2; i <= n; i++){//先存储要排序的元素int tmp = a[i];//依次和前面的元素比较int j = i - 1;while ( a[j] > tmp&&j >= 1){a[j+1] = a[j];j--;}//当出循环时,要么a[j]<=tmp,要么遍历完已排序序列//直接在j+1的位置放入元素a[j+1] = tmp;}
}
int main()
{cin >> n;//从a[1]开始放入元素for (int i = 1; i <= n; i++) cin >> a[i];//插入排序insert_sort();for (int i = 1; i <= n; i++)cout << a[i] << " ";return 0;
}
2. 选择排序
2.1 算法思想
每次找出未排序序列的最小元素,然后放入有序序列后面
时间复杂度:总会遍历一遍所有未排序序列,时间复杂度O(n^2)
2.2 代码实现
#include<iostream>
using namespace std;const int N = 1e5 + 10;
int a[N];
int n;void selection_sort()
{//待排序序列为 [i,n]for (int i = 1; i < n; i++){//从 [i,n] 中选择最小值的位置int pos = i;for (int j = i+1; j <= n; j++){if (a[pos] > a[j]) pos = j;}//进行交换,将最小元素放入有序序列后面swap(a[i], a[pos]);}
}int main()
{cin >> n;//从a[1]开始放入元素for (int i = 1; i <= n; i++) cin >> a[i];//选择排序selection_sort();for (int i = 1; i <= n; i++)cout << a[i] << " ";return 0;
}
3. 冒泡排序
3.1 算法思想
进行 n -1 趟操作,每一趟进行多次比较,每次比较相邻的两个元素,如果满足排序条件,就交换;每趟可以将一个元素放到正确位置,像气泡一样,气泡大的慢慢冒出来,较大的数慢慢到最终的位置上
对于最朴素的冒泡排序,如果数组本身就是升序,还是会进行 n -1 趟操作,时间复杂度O(n^2)
但我们可以进行优化,如果有一趟操作,所有的元素都没有交换,证明数组已经是升序了,不用进行接下来的操作
优化后的冒泡排序时间复杂度:
1. 数组升序,只扫描一遍,时间复杂度O(n)
2. 数组逆序,时间复杂度O(n^2)
3.2 代码实现
#include<iostream>
using namespace std;const int N = 1e5 + 10;
int a[N];
int n;void bubble_sort()
{//进行 n - 1 趟排序for (int i = n; i > 1; i--){//标记是否交换元素bool flag = false;// [ 1,i] 为待排序区间for (int j = 1; j < i; j++){//每一趟比较相邻元素if (a[j] > a[j + 1]){swap(a[j], a[j + 1]);flag = true;}}//如果没交换元素,直接结束if (flag==false) return;}
}int main()
{cin >> n;//从a[1]开始放入元素for (int i = 1; i <= n; i++) cin >> a[i];//冒泡排序bubble_sort();for (int i = 1; i <= n; i++)cout << a[i] << " ";return 0;
}
4. 堆排序
4.1 算法思想
本质是优化选择排序,将数据放入堆(堆和STL —— priority——queue)中,可以快速得到待排序元素的最小值或最大值
步骤:1. 建堆,升序大根堆,降序小根堆。
注意: 建堆不是新建一个堆结构,将数据放入新建的堆结构中。而是将数组的逻辑结构化为堆结构
具体方法:从倒数第一个非叶子结点开始,倒着到根结点位置,每个结点向下调整
2. 排序,每次将堆顶元素和堆最后一个元素交换,堆元素就少一个,将堆顶元素向下调整。直到堆剩一个元素
时间复杂度:1. 建堆的时间复杂度通过每个结点的调整层数计算约为O(n)
2. 排序的时间复杂度为O(nlog n)
所以总的时间复杂度为O(nlog n)
4.2 代码实现
#include<iostream>
using namespace std;const int N = 1e5 + 10;
int a[N];
int n;//向下调整
void down(int parent, int len)
{int child = parent * 2;while (child <= len){if (child + 1 <= len && a[child] < a[child+1])child++;if (a[parent] >= a[child])return;swap(a[parent], a[child]);parent = child;child = parent * 2;}
}void heap_sort()
{//建堆,从第一个非叶结点开始for (int i = n / 2; i >= 1; i--){down(i, n);}//排序for (int i = n; i > 1; i--){swap(a[i], a[1]);//堆元素减去1down(1, i-1);}
}
int main()
{cin >> n;//从a[1]开始放入元素for (int i = 1; i <= n; i++) cin >> a[i];//堆排序heap_sort();for (int i = 1; i <= n; i++)cout << a[i] << " ";return 0;
}
5. 快速排序
5.1 算法思想
5.1.1 常规快排
在待排序区间任取一个元素作为基准元素,按照这个基准元素的大小将区间元素分为左右两个部分,左边区间元素小于基准元素,右边区间元素大于等于基准元素。再递归排序基准值左区间和基准值右区间(其实,快速排序有点像树的先序遍历)
5.1.2 优化
有两种极端情况:
a. 如果每次选择基准元素为待排序序列的最左边元素,那如果整个序列升序,右区间每次划分都会很长,递归层数就是 n 层,那时间复杂度就退化为O(n^2)
b. 如果每次选择基准元素为待排序序列的中间元素,那如果整个序列为相同元素,那时间复杂度依旧会退化为O(n^2)
优化一:随机选择基准元素
#include<iostream>
#include<ctime>
using namespace std;int main()
{//种下一个种子srand(time(0));//获得一个随机数rand();return 0;
}
优化二:数组分三块(数组分块问题 【刷题反思】-CSDN博客)
按基准元素,小于基准元素的放入左边区间,等于基准元素的放入中间区间,大于基准元素的放入右边区间。中间区间不用管,递归处理左右区间即可
经过优化,块排的时间复杂度为O(nlog n)
5.2 代码实现
#include<iostream>
#include<ctime>
using namespace std;const int N = 1e5 + 10;
int a[N];
int n;int get_rand(int left,int right)
{//保证随机元素在区间内return a[rand() % (right - left + 1) + left];
}void quick_sort(int left, int right)
{//递归结束条件if (left >= right) return;//得到随机基准元素int q = get_rand(left,right);//排序,数组分三块int l = left - 1, i = left, r = right + 1;while (i < r){if (a[i] < q) swap(a[++l], a[i++]);else if (a[i] == q)i++;else swap(a[--r], a[i]);}//递归处理左右区间quick_sort(left, l);quick_sort(r, right);
}
int main()
{cin >> n;//从a[1]开始放入元素for (int i = 1; i <= n; i++) cin >> a[i];//快速排序//种下一个随机数种子srand(time(0));quick_sort(1,n);for (int i = 1; i <= n; i++)cout << a[i] << " ";return 0;
}
6. 归并排序
6.1 算法思想
归并排序的思想是分治思想,先将整个数组区间从中间一分为二,然后把左右区间排序合并。这是递归实现的,每次都将先将区间一分为二,再排序(这一过程类似树的后序遍历)
时间复杂度:每次都是一分为二,时间复杂度可以稳定O(nlog n)
6.2 代码实现
#include<iostream>
using namespace std;const int N = 1e5 + 10;
int a[N];
int n;//创建辅助数组合并两个有序序列
int tmp[N];
void merge_sort(int left, int right)
{//递归结束条件if (left >= right) return;//先一分为二int mid = (left + right) / 2;//左右区间先有序merge_sort(left, mid);merge_sort(mid + 1, right);//合并左右两个有序区间int cur1 = left, cur2 = mid+1, i = left;while (cur1 <= mid && cur2 <= right){if (a[cur1] <= a[cur2]) tmp[i++] = a[cur1++];else tmp[i++] = a[cur2++];}while (cur1 <= mid)tmp[i++] = a[cur1++];while(cur2 <= right)tmp[i++] = a[cur2++];for (int j = left; j <= right; j++){a[j] = tmp[j];}
}
int main()
{cin >> n;//从a[1]开始放入元素for (int i = 1; i <= n; i++) cin >> a[i];//归并排序merge_sort(1,n);for (int i = 1; i <= n; i++)cout << a[i] << " ";return 0;
}
相关文章:
常见的排序算法 【复习笔记】
注意: 1. 后面的排序算法实现都只考虑升序,对于逆序,只有知道原理,实现很容易 2. 案例题: 题目描述:将读入的 N 个数从小到大输出 ( 1 < N <10e5) 输入描述:第一行一个正整数 N 第二行…...
【经验分享】Ubuntu20.04 vmware虚拟机存储空间越来越小问题(已解决)
【经验分享】Ubuntu20.04 vmware虚拟机存储空间越来越小问题(已解决) 前言一、问题分析二、解决方案 前言 我们在使用虚拟机过程中,经常会碰到即使删除了一些文件,但是存储空间还是越来越小的问题。今天我们来解决下这个问题。 一…...
Jenkins-自动化部署-通知
场景 使用jenkins部署,但有时不能立马部署,需要先通知相关人员,再部署,如果确实不能部署,可以留时间撤销。 方案 1.开始前我们添加,真正开始执行的等待时间;可供选择(Choice Param…...
Qt 文件操作+多线程+网络
文章目录 1. 文件操作1.1 API1.2 例子1,简单记事本1.3 例子2,输出文件的属性 2. Qt 多线程2.1 常用API2.2 例子1,自定义定时器 3. 线程安全3.1 互斥锁3.2 条件变量 4. 网络编程4.1 UDP Socket4.2 UDP Server4.3 UDP Client4.4 TCP Socket4.5 …...
《基于Hadoop的青岛市旅游景点游客行为分析系统设计与实现》开题报告
目录 一、选题依据 1.选题背景 2.国内外研究现状 (1)国内研究现状 (2)国外研究现状 3.发展趋势 4.应用价值 二、研究内容 1.学术构想与思路 2. 拟解决的关键问题 3. 拟采取的研究方法 4. 技术路线 (1)旅游前准备阶段 …...
pycharm debug卡住
pycharm debug时一直出现 collecting data, 然后点击下一行就卡住。 勾选 Gevent compatible解决 https://stackoverflow.com/questions/39371676/debugger-times-out-at-collecting-data...
MyBatis-Plus 元对象处理器 @TableField注解 反射动态赋值 实现字段自动填充
目录 🌰 举个直观例子 🛠️ 核心作用原理 📜 代码级工作流程 📜 完整代码 🔍 关键概念拆解 ⚠️ 常见问题排查 🌟 设计意义 🌰 举个直观例子 package work.dduo.ans.domain;import com.b…...
ISP 常见流程
1.sensor输出:一般为raw-OBpedestal。加pedestal避免减OB出现负值,同时保证信号超过ADC最小电压阈值,使信号落在ADC正常工作范围。 2. pedestal correction:移除sensor加的基底,确保后续处理信号起点正确。 3. Linea…...
Python Cookbook-2.27 从微软 Word 文档中抽取文本
任务 你想从 Windows 平台下某个目录树中的各个微软 Word 文件中抽取文本,并保存为对应的文本文件。 解决方案 借助 PyWin32 扩展,通过COM 机制,可以利用 Word 来完成转换: import fnmatch,os,sys,win32com.client wordapp w…...
java数据结构_Map和Set(一文理解哈希表)_9.3
目录 5. 哈希表 5.1 概念 5.2 冲突-概念 5.3 冲突-避免 5.4 冲突-避免-哈希函数的设计 5.5 冲突-避免-负载因子调节 5.6 冲突-解决 5.7 冲突-解决-闭散列 5.8 冲突-解决-开散列 / 哈希桶 5.9 冲突严重时的解决办法 5. 哈希表 5.1 概念 顺序结构以及平衡树中&#x…...
基于SpringBoot的“数据驱动的资产管理系统站”的设计与实现(源码+数据库+文档+PPT)
基于SpringBoot的“数据驱动的资产管理系统站”的设计与实现(源码数据库文档PPT) 开发语言:Java 数据库:MySQL 技术:SpringBoot 工具:IDEA/Ecilpse、Navicat、Maven 系统展示 系统功能结构图 局部E-R图 系统登录界…...
excel 斜向拆分单元格
右键-合并单元格 右键-设置单元格格式-边框 在设置好分割线后,你可以开始输入文字。 需要注意的是,文字并不会自动分成上下两行。 为了达到你期望的效果,你可以通过 同过左对齐、上对齐 空格键或使用【AltEnter】组合键来调整单元格中内容的…...
深入理解推理语言模型(RLM)
大语言模型从通用走向推理,万字长文解析推理语言模型,建议收藏后食用。 本文基于苏黎世联邦理工学院的论文《Reasoning Language Models: A Blueprint》进行整理,你将会了解到: 1、RLM的演进与基础:RLM融合LLM的知识广…...
2025年具有百度特色的软件测试面试题
百度业务场景 如何测试一个高并发的搜索系统(如百度搜索)?如何测试一个在线地图服务(如百度地图)?如何测试一个大型推荐系统(如百度推荐)的性能?百度技术栈 你对百度的 PaddlePaddle 框架有了解吗?如何测试基于 PaddlePaddle 的服务?如何测试百度云的 API 服务?你对…...
HOW - 在Windows浏览器中模拟MacOS的滚动条
目录 一、原生 CSS 代码实现模拟 macOS 滚动条额外优化应用到某个特定容器 二、使用第三方工具/扩展 如果你想让 Windows 里的滚动条 模拟 macOS 的效果(细窄、圆角、隐藏默认轨道)。 可以使用以下几种方案: 一、原生 CSS 代码实现 模拟 m…...
Lua | 每日一练 (5)
💢欢迎来到张胤尘的技术站 💥技术如江河,汇聚众志成。代码似星辰,照亮行征程。开源精神长,传承永不忘。携手共前行,未来更辉煌💥 文章目录 Lua | 每日一练 (5)题目参考答案浅拷贝深拷贝使用场景…...
C# Unity 唐老狮 No.5 模拟面试题
本文章不作任何商业用途 仅作学习与交流 安利唐老狮与其他老师合作的网站,内有大量免费资源和优质付费资源,我入门就是看唐老师的课程 打好坚实的基础非常非常重要: 全部 - 游习堂 - 唐老狮创立的游戏开发在线学习平台 - Powered By EduSoho 如果你发现了文章内特殊的字体格式,…...
云原生事件驱动架构:构建实时响应的数字化神经系统
引言:重塑企业实时决策能力 Uber实现事件驱动架构升级后,实时供需匹配延迟降至8ms,动态定价策略响应速度提升1200倍。Netflix通过事件流处理实现个性化推荐,用户点击率提高34%,事件处理吞吐量达2000万/秒。Confluent基…...
Metasploit multi/handler 模块高级选项解析
multi/handler 是 Metasploit 框架中至关重要的模块,主要用于监听目标机的连接并处理来自目标的反向 shell 或会话。它可以灵活地适应不同渗透测试场景,提供高度的自定义选项以优化监听器的行为。 在 Metasploit msf6 框架中,当使用 exploit…...
WPF高级 | WPF 应用程序部署与发布:确保顺利交付到用户手中
WPF高级 | WPF 应用程序部署与发布:确保顺利交付到用户手中 一、前言二、部署与发布基础概念2.1 部署的定义与目的2.2 发布的方式与渠道2.3 部署与发布的关键要素 三、WPF 应用程序打包3.1 使用 Visual Studio 自带的打包工具3.2 使用第三方打包工具 四、发布到不同…...
Spring MVC 程序开发(1)
目录 1、什么是 SpringMVC2、返回数据2.1、返回 JSON 对象2.2、请求转发2.3、请求重定向2.4、自定义返回的内容 1、什么是 SpringMVC 1、Tomcat 和 Servlet 分别是什么?有什么关系? Servlet 是 java 官方定义的 web 开发的标准规范;Tomcat 是…...
JavaWeb后端基础(6)
主键返回 例子: /** * 新增员工数据 */ Options(useGeneratedKeys true, keyProperty "id") Insert("insert into emp(username, name, gender, phone, job, salary, image, entry_date, dept_id, create_time, update_time) " "value…...
C# Unity 唐老狮 No.4 模拟面试题
本文章不作任何商业用途 仅作学习与交流 安利唐老狮与其他老师合作的网站,内有大量免费资源和优质付费资源,我入门就是看唐老师的课程 打好坚实的基础非常非常重要: 全部 - 游习堂 - 唐老狮创立的游戏开发在线学习平台 - Powered By EduSoho 如果你发现了文章内特殊的字体格式,…...
集群、分布式与微服务架构 区别
集群、分布式与微服务架构:概念解析与核心差异 在构建现代软件系统时,集群架构、分布式系统和微服务架构是三种常见的技术方案。它们常被混淆,但各自解决的问题、设计理念和应用场景截然不同。本文将从基础概念出发,深入分析三者…...
Protocol Buffers在MCU上的nanopb介绍及使用详解
在嵌入式系统和资源受限的环境中,传统的Protocol Buffers 可能显得过于庞大。因此,nanopb 应运而生,它是一个轻量级的 Protocol Buffers 生成器,专为嵌入式系统设计c语言设计。本文将介绍如何安装和使用 nanopb,以及通…...
【Elasticsearch】自定义内置的索引生命周期管理(ILM)策略。
以下是对 Elasticsearch 官方教程《Customize built-in ILM policies》的详细解读,结合原文内容,帮助您更好地理解如何自定义内置的索引生命周期管理(ILM)策略。 --- Elasticsearch 教程:自定义内置 ILM 策略 1.背景…...
测试工程师Ai应用实战指南简例prompt
以下是一个真实具体的案例,展示测试工程师如何在不同阶段结合DeepSeek提升效率。案例基于电商平台"订单超时自动关闭"功能测试: 案例背景 项目名称:电商平台订单系统V2.3 测试目标:验证"用户下单后30分钟未支付,订单自动关闭并释放库存"功能 技术栈:…...
(十 二)趣学设计模式 之 享元模式!
目录 一、 啥是享元模式?二、 为什么要用享元模式?三、 享元模式的实现方式四、 享元模式的优缺点五、 享元模式的应用场景六、 总结 🌟我的其他文章也讲解的比较有趣😁,如果喜欢博主的讲解方式,可以多多支…...
Trae:国内首款AI原生IDE,编程效率大提升
今年一月,在新闻上看到字节跳动面向海外市场推出了一款名为Trae的AI集成开发环境(IDE)。起初,我并未给予过多关注,因为市面上已有不少IDE集成了AI插件,功能也非常全面,而字节跳动自家的MarsCode…...
深入解析 Vue Router 的 beforeEach:功能、用法与实践指南
什么是 beforeEach?基本语法与参数解析next() 的 4 种调用方式常见使用场景与代码示例动态路由加载的实践技巧常见陷阱与避坑指南总结 1. 什么是 beforeEach? beforeEach 是 Vue Router 提供的 全局前置守卫(Global Before Guards࿰…...
