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

算法:选择排序+堆排序

选择排序

基于"选择"的排序

思路

把整个序列分为 有序区 和 无序区。
初始时,有序区为空,无序区是整个数组。
每一趟从 无序区 里选择一个最小元素,放到无序区的第一个位置。
这样,有序区的长度 +1,无序区的长度 -1。
重复这个过程,直到所有元素都进入有序区(只需要执行 n-1 趟)。
举一个例子:
数组:[64, 25, 12, 22, 11]
第1趟:最小数是 11 → 与第1个元素交换 → [11, 25, 12, 22, 64]
第2趟:最小数是 12 → 与第2个元素交换 → [11, 12, 25, 22, 64]
第3趟:最小数是 22 → 与第3个元素交换 → [11, 12, 22, 25, 64]
第4趟:最小数是 25 → 与第4个元素交换 → [11, 12, 22, 25, 64]
排序完成

代码

代码也很好写

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <unordered_map>
#include <limits.h>
#include <queue>
#include <string.h>
#include <stack>
using namespace std;
void select_sort(vector<int>& arr)
{for(int i=0;i<arr.size()-1;i++){int minn=arr[i];int minindex=i;for(int j=i+1;j<arr.size();j++){if(minn>arr[j]){minn=arr[j];minindex=j;}}swap(arr[i],arr[minindex]);	}
}
int main()
{//ios::sync_with_stdio(0),cin.tie(0),cout.tie(vector<int> arr = {64, 25, 12, 22, 11};select_sort(arr); for(int i=0;i<arr.size();i++){cout<<arr[i]<<" ";}return 0;} 

时间复杂度

O(n^2)

稳定性

选择排序是不稳定的
例如数组 [5(前), 5(后), 3]
第一趟选择最小值 3,与第一个 5 交换 → [3, 5(后), 5(前)]
两个相同元素的相对顺序发生了改变。
原因:交换操作可能会把后面的相等元素提前。

就地性

选择排序:是就地排序,因为只需要少量辅助变量 minindex 和循环下标。

内部排序

因为所有待排序记录可以⼀次载⼊内存时,因此它是内部排序。

优化

我们知道选择排序的时间复杂度为O(n^2)时间复杂度是很大的,那么我们有没有什么办法可以把它降低一些呢?
选择排序中需要跑n-1趟是无法优化的,能优化的就是在找最小值这里,我们原来是通过遍历来找最小值,现在我们可以借助堆来优化使得时间复杂度从O(n)降低到O(logn).
那么什么是堆呢?
这里用一篇文章讲清堆:

数据结构:堆

由此引出堆排序。

堆排序

堆排序我看发现有两种方法,一种是用小顶堆输出堆顶,再重复删除堆顶,直到堆为空,但这样改变了原本数组的元素位置,虽然输出的是堆排序,但原数组并不是按堆排序存放,这是一种缺陷
它的时间复杂度为建立小顶堆的O(n)*删除堆顶元素的O(logn)
总共为O(nlogn)
另一种是建立大顶堆,再交换堆顶到末尾,然后缩小堆,调整堆,这种方法保留排序的过程,并且是原地排序,排序后的数组也是有序的,感觉这种方法是最合适的。它的时间复杂度同样是O(nlogn
因此我们这里就采用大顶堆+交换堆顶的方法来实现堆排序。
完整代码如下:

#include <iostream>
#include <vector>
using namespace std;// 下沉操作(维护大顶堆)
void heapify(vector<int>& arr, int n, int i) {int largest = i;          // 假设父节点最大int left = 2 * i + 1;     // 左孩子int right = 2 * i + 2;    // 右孩子if (left < n && arr[left] > arr[largest])largest = left;if (right < n && arr[right] > arr[largest])largest = right;if (largest != i) {swap(arr[i], arr[largest]);heapify(arr, n, largest); // 递归下沉}
}// 堆排序
void heapSort(vector<int>& arr) {int n = arr.size();// 1. 建立大顶堆for (int i = n / 2 - 1; i >= 0; i--) {heapify(arr, n, i);}// 2. 交换堆顶与末尾元素,然后调整堆for (int i = n - 1; i >= 1; i--) {swap(arr[0], arr[i]);       // 堆顶最大值放到末尾heapify(arr, i, 0);         // 重新调整堆,范围缩小}
}int main() {vector<int> arr = {12, 11, 13, 5, 6, 7};cout << "排序前: ";for (int x : arr) cout << x << " ";cout << endl;heapSort(arr);cout << "升序排序后: ";for (int x : arr) cout << x << " ";cout << endl;return 0;
}

堆排序相对交换排序的时间复杂度下降到O(nlogn)
是一种进步,它是就地排序,因为它没有借助其他数组,它不稳定因为它在排序的过程中会改变数组的相对位置。
举例:
数组:[4a, 5, 3, 4b, 1](4a 和 4b 值相同,但是不同元素)
建大顶堆 → 堆顶 5
交换堆顶 5 和末尾 1 → [1,4a,3,4b,5]
堆化 → [4a,1,3,4b,5]
继续交换堆顶 4a 和末尾 4b → [4b,1,3,4a,5]
发现 4a 和 4b 的相对顺序被改变了 → 不稳定
总结:堆排序
时间复杂度:O(n log n)
空间复杂度:O(1)(原地)
稳定性:不稳定


文章转载自:

http://T7ARWuix.ydfLc.cn
http://xDHkXROF.ydfLc.cn
http://nJRl0ycv.ydfLc.cn
http://MVUjcYKB.ydfLc.cn
http://1ImNDPG8.ydfLc.cn
http://sw3QbjHP.ydfLc.cn
http://SpqITkz7.ydfLc.cn
http://FbISi5FS.ydfLc.cn
http://qWkZ9qnH.ydfLc.cn
http://U109cXVX.ydfLc.cn
http://x8axphCY.ydfLc.cn
http://QedeTihS.ydfLc.cn
http://V6SmkTDw.ydfLc.cn
http://qHo1jGuO.ydfLc.cn
http://PaQ7rFZ7.ydfLc.cn
http://tP4aC3VP.ydfLc.cn
http://mFLkcg3l.ydfLc.cn
http://1eschYCW.ydfLc.cn
http://kSPR4qyN.ydfLc.cn
http://M0kC2mzN.ydfLc.cn
http://QjSHnjZL.ydfLc.cn
http://McaEWX87.ydfLc.cn
http://l8E3Jron.ydfLc.cn
http://62PSzmX3.ydfLc.cn
http://CAnrm9de.ydfLc.cn
http://f3JSGKQ8.ydfLc.cn
http://ZDUf7zt7.ydfLc.cn
http://2uGbKrM2.ydfLc.cn
http://dgi8Q65p.ydfLc.cn
http://TS6T616r.ydfLc.cn
http://www.dtcms.com/a/371475.html

相关文章:

  • UE4/UE5反射系统动态注册机制解析
  • 【开题答辩全过程】以 汽车知名品牌信息管理系统为例,包含答辩的问题和答案
  • rabbitmq 的 TTL
  • Linux内核网络的连接跟踪conntrack简单分析
  • Java Stream流:从入门到精通
  • java常见面试题杂记
  • SAP匈牙利新闻
  • Java全栈工程师的面试实战:从基础到高阶技术解析
  • 计算机毕设选题:基于Python+Django的B站数据分析系统的设计与实现【源码+文档+调试】
  • 【嵌入式】【树莓派】【大疆PSDK】用树莓派4B开发大疆行业无人机应用系统小结-【硬件篇】
  • 深度学习——自然语言处理NLP
  • 灾难性遗忘:神经网络持续学习的核心挑战与解决方案
  • bug | 事务粒度不能太大,含demo
  • 如何建立针对 .NET Core web 程序的线程池的长期监控
  • 41个开源大语言模型基准测试报告
  • unsloth 笔记:从最近的检查点继续微调
  • 区域导航系统 | 印度区域卫星导航系统(IRNSS/NavIC)深度解析
  • Linux服务器资源自动监控与报警脚本详解
  • 社交新零售时代本地化微商的发展路径研究——基于开源AI智能名片链动2+1模式S2B2C商城小程序源的创新实践
  • Tailwind CSS v4 终极指南:体验 Rust 驱动的闪电般性能与现代化 CSS 工作流
  • 模块--红外跟随避障模块
  • 使用MQTT.fx和ESP32连接Onenet平台
  • 功率器件固晶挑战:抗高温翘曲治具提升IGBT焊接强度30%
  • Text2Sql.Net架构深度解析:从自然语言到SQL的智能转换之道
  • UE5 基础应用 —— 10 - 控制台命令
  • Linux内核Syncookies机制:抵御SYN Flood攻击的坚实防线
  • Axum 最佳实践:如何构建优雅的 Rust 错误处理系统?(三)
  • 使用 nginx-module-vts 进行 Nginx 流量监控
  • 心路历程-Linux如何赋予权限?
  • 实验室服务器配置|通过Docker实现Linux系统多用户隔离与安全防控