排序算法之选择排序堆排序

news2024/12/1 11:18:11
算法时间复杂度辅助空间复杂度稳定性
选择排序O(N^2)O(1)不稳定
堆排序O(NlogN)O(1)不稳定

1.选择排序

这应该算是最简单的排序算法了,每次在右边无序区里选最小值,没有无序区时,就宣告排序完毕

比如有一个数组:[2,3,2,6,5,1,4]排序过程如下:

(注意:开始时,蓝色2的下标比红色2

[2,3,2,6,5,1,4]有序区 []

从[2,3,2,6,5,1,4]中选取最小值1

交换1和2

[1,3,2,6,5,2,4]有序区[1]

从[3,2,6,5,2,4]中选取最小值2

交换23

[1,2,3,6,5,2,4]有序区[1,2]

从[3,6,5,2,4]中选取最小值2

交换23

[1,2,2,6,5,3,4]有序区[1,2,2]

从[6,5,3,4]中选取最小值3

交换6和3

[1,2,2,3,5,6,4]有序区[1,2,2,3]

从[5,6,4]中选取最小值4

交换4和5

[1,2,2,3,4,6,5]有序区[1,2,2,3,4]

从[6,5]中选取最小值5

交换5和6

[1,2,2,3,4,5,6]有序区[1,2,2,3,4,5,6]

排序完毕 

可以发现排序之后蓝色2的下标比红色2大,所以选择排序不稳定

鱿鱼选择排序每次都要扫描一遍数组,时间复杂度O(n)而要进行n次扫描操作,所以时间复杂度为O(n*n)

动图 

#include<bits/stdc++.h>
using namespace std;
int main(){
	int a[100000],n;
	cin>>n;
	for(int i=0;i<n;i++){
		cin>>a[i];
	}
	for(int i=0;i<n-1;i++){
		int mn=i;
		for(int j=i+1;j<n;j++){
			if(a[j]<a[mn]){
				mn=j;
			}
		}
		swap(a[i],a[mn]);
	}
	for(int i=0;i<n;i++){
		cout<<a[i]<<' ';
	}
	return 0;
}

由于效率过低,通过不了此题 (提交记录)

2.堆排序

是选择排序的改进版

要了解堆排序,首先得了解完全二叉树

2.1完全二叉树

定义:若设二叉树的深度为h除第 h 层外其它各层 (1~h-1) 的结点数都达到最大个数(即1~h-1层为一个满二叉树),第 h 层所有的结点都连续集中在最左边,这就是完全二叉树。

举个栗子

这是完全二叉树

这不是

这也不是

有用的芝士:在完全二叉树中,

节点的左孩子下标= 该节点的下标*2+1,

节点的右孩子下标= 该节点的下标*2+2(第一个元素下标为0)

2.2堆

堆是一种特殊的完全二叉树分为大根堆小根堆!

大根堆大根堆的每个父节点>=父节点对应的子节点

反之亦然

这个是大根堆

堆用数组来存储,存储方式:第一层(根)下标:0第二层:1,2第三次:3,4,5,6,以此类推

比如上图,物理存储结构是:[30,20,10,15,3,8,2,1,10,3] 

2.3堆排序

        2.3.1建堆

        分为向上调整算法和向下调整算法

        向上调整法建堆时间复杂度:nlogn(太弱了

        向下调整法建堆时间复杂度:O(n)

        建堆过程以向下调整法建大根堆为例

        向下调整:如果父节点比大的孩子小,则两者交换位置,然后进行新一轮比较,直到叶子或            父节点不小于大的孩子

        建堆:对每个非叶子节点进行向下调整即可

    

          建堆的代码

void mswap(int* a,int * b){//交换函数
	int t=*b;
	*b=*a;
	*a=t;
	return;
}
void down(int pa,int n){
	int chl=pa*2+1;//左孩子
	while(chl<n){
		if(chl+1<n&&f[chl+1]>f[chl]){chl++;}//如果右孩子大于左孩子
		if(f[chl]>f[pa]){
			mswap(f+chl,f+pa);
			pa=chl;
			chl=pa*2+1;//开启新一轮比较
		}
		else{
			break;//不满足条件
		}
	}
}
void makeheap(){
	int flag=n/2;//叶子节点不用比较
	for(int i=flag;i>=0;i--){
		down(i,n);
	}
}

        2.3.2排序

        根据刚才的内容,相信大家都发现了在大(小)根堆中,根节点最大(小)

        于是把堆顶移除就可以排好一个元素,但是移除应该把堆顶和最后一个交换,否则会严重破坏堆序性,增加复杂度!

        这样写只要把新堆顶进行调整即可~~

        所以排序部分就是:

        1.移除堆顶

        2.向下调整新堆顶

        3.重复以上步骤,直到堆空

        上代码

#include<bits/stdc++.h>
using namespace std;
int f[100005],n;
void mswap(int* a,int * b){//自己写的交换
	int t=*b;
	*b=*a;
	*a=t;
	return;
}
void down(int pa,int n){
	int chl=pa*2+1;//左孩子
	while(chl<n){//父亲必须是非叶子节点(条件也可以是pa<n/2)
		if(chl+1<n&&f[chl+1]>f[chl]){chl++;}//如果右孩子比左孩子大
		if(f[chl]>f[pa]){
			mswap(f+chl,f+pa);
			pa=chl;
			chl=pa*2+1;//继续向下调整
		}
		else{
			break;//不满足
		}
	}
}
void heapsort(){
	int flag=n/2;
	for(int i=flag;i>=0;i--){
		down(i,n);
	}//建堆
	for(int i=n-1;i>0;i--){
		mswap(f,f+i);
		down(0,i);
	}//排序
}
int main(){
	cin>>n;
	for(int i=0;i<n;i++) cin>>f[i];
	heapsort();
	for(int i=0;i<n;i++) cout<<f[i]<<' ';
	return 0;//好习惯
}

2.4STL的做法

STL的优先队列底层用堆实现,所以

 

#include<bits/stdc++.h>
using namespace std;
int main(){
	priority_queue<int,vector<int>,greater<int> > q;//注意两个">"要用空格分隔
	int n;
	cin>>n;
	for(int i=0;i<n;i++){
		int a;
		cin>>a;
		q.push(a);
	}
	for(int i=0;i<n;i++){
		cout<<q.top()<<' ';
		q.pop();
	}
	return 0;
}

有STL前面的白看了但是STL比手打堆慢一倍!

 

2.5效率分析

堆排序建堆时间忽略不计!O(n),需要N次交换+调整,调整复杂度为logn所以时间复杂度为O(NlogN)

稳定性:由于是改进版的选择排序,所以不稳定!

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

从0开始linux(39)——线程(2)线程控制

欢迎来到博主的专栏&#xff1a;从0开始linux 博主ID&#xff1a;代码小豪 文章目录 线程创建线程标识符线程参数多线程竞争资源 回收线程detach 线程退出pthread_cancel 线程创建 线程创建的函数为pthread_create。该函数是包含在posix线程库当中&#xff0c;posix线程是C语言…

28.100ASK_T113-PRO Linux+QT 显示一张照片

1.添加资源文件 2. 主要代码 #include "mainwindow.h" #include "ui_mainwindow.h" #include <QImage> #include <QPixmap>MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow) {ui->setupUi(this);QIm…

不用下载安装的线上3D编辑器,支持哪些功能?

线上3D编辑器&#xff0c;不用下载软件&#xff0c;直接通过浏览器打开51建模网&#xff0c;上传模型即可进入编辑器&#xff0c;不仅支持对3D模型进行细致的效果配置&#xff0c;如光源设置、背景定制、材质调节等&#xff0c;还具备爆炸效果、热点动画、部件替换等高级交互功…

C语言——指针初阶(三)

目录 一.指针-指针 代码1&#xff1a; 运行结果&#xff1a; 代码2&#xff1a; 运行结果&#xff1a; 代码3&#xff1a; 运行结果&#xff1a; 二.指针数组 例&#xff1a; 往期回顾 一.指针-指针 指针减去指针的前提&#xff1a;两个指针指向同一块空间。 指针减去指针…

vue3项目创建方式记录

目录 创建vue3常用的方式有三种&#xff1a;一.使用vue cli创建二.使用vite创建三.使用vue3官方推荐创建方式&#xff08;create-vue&#xff09; 创建vue3常用的方式有三种&#xff1a; 一.使用vue cli创建 vue create 项目名二.使用vite创建 vite是下一代前端开发与构建工…

基于特征子空间的高维异常检测:一种高效且可解释的方法

本文将重点探讨一种替代传统单一检测器的方法&#xff1a;不是采用单一检测器分析数据集的所有特征&#xff0c;而是构建多个专注于特征子集(即子空间)的检测器系统。 在表格数据的异常检测实践中&#xff0c;我们的目标是识别数据中最为异常的记录&#xff0c;这种异常性可以…

MySQL —— MySQL 程序

目录 前言 一、MySQL 程序简介 二、mysqld -- MySQL 服务器 三、mysql -- MySQL 客户端 1. mysql 客户端简介 2. mysql 客户端选项 &#xff08;1&#xff09;指定选项的方式 &#xff08;2&#xff09;mysql 客户端命令常用选项 &#xff08;3&#xff09;在命令行中使…

Flink CDC 使用实践以及遇到的问题

背景 最近公司在做一些业务上的架构调整&#xff0c;有一部分是数据从mysql采集到Starrocks&#xff0c;之前的一套方法是走 debezium 到 puslar 到 starrocks,这一套下来比较需要配置很多东西&#xff0c;而且出现问题以后&#xff0c;需要修改很多配置&#xff0c;而且现阶段…

数据链路层(三)--点对点通信协议PPP

PPP协议叫做点对点协议&#xff0c;是目前使用的最广泛的数据链路层协议。 1 PPP协议的特点 用户通常需要连接到某个ISP才能接入互联网&#xff0c;PPP协议就是用户计算机和ISP进行通信所使用的数据链路层协议。 1.1 PPP协议应满足的需求 &#xff08;1&#xff09;简单&…

C语言 分支语句(if)

分支语句(if) if语句形式一 适用只有一个分支判断 if(表达式1) //如果 { 语句块1 } if语句形式二 适用有两个分支判断 if(表达式1) //如果 { 语句块1 } else //否则 { 语句块2 } 例:求方程的根 if语句形式三 适用多分支判断 if(表达式1) //多分支 { 语句块1 } else if(表达…

如何将WSL的虚拟机安装到任意目录中

目录 引言 下载安装包 解压安装包 手工安装 结语 引言 WSL默认是将虚拟机安装在C盘的用户目录下&#xff0c;如果长时间使用Windows后&#xff0c;可能C盘的空间就会非常吃紧&#xff0c;所以非常希望把虚拟机安装到C盘以外的目录中。本文就介绍一下相关的工作。 这里只讨…

一款.NET开源的Windows资源管理器标签页工具

前言 今天大姚给大家分享一款基于.NET开发的可以让你在Windows资源管理器中使用Tab多标签功能的小工具&#xff1a;QTTabBar。 工具介绍 QTTabBar是一款基于.NET开发的可以让你在Windows资源管理器中使用Tab多标签功能的小工具。从此以后工作时不再遍布文件夹窗口&#xff0c…

传输控制协议(TCP)

传输控制协议是Internet一个重要的传输层协议。TCP提供面向连接、可靠、有序、字节流传输服务。 1、TCP报文段结构 注&#xff1a;TCP默认采用累积确认机制。 2、三次握手、四次挥手 &#xff08;1&#xff09;当客户向服务器发送完最后一个数据段后&#xff0c;发送一个FIN段…

c++哈希表(原理、实现、开放寻址法)适合新手

c系列哈希的原理及实现&#xff08;上&#xff09; 文章目录 c系列哈希的原理及实现&#xff08;上&#xff09;前言一、哈希的概念二、哈希冲突三、哈希冲突解决3.1、开放寻址法3.2、删除操作3.3、负载因子四、代码实现 总结 前言 红黑树平衡树和哈希有不同的用途。 红黑树、…

服务器数据恢复—raid6阵列硬盘被误重组为raid5阵列的数据恢复案例

服务器存储数据恢复环境&#xff1a; 存储中有一组由12块硬盘组建的RAID6阵列&#xff0c;上层linux操作系统EXT3文件系统&#xff0c;该存储划分3个LUN。 服务器存储故障&分析&#xff1a; 存储中RAID6阵列不可用。为了抢救数据&#xff0c;运维人员使用原始RAID中的部分…

Python酷库之旅-第三方库Pandas(250)

目录 一、用法精讲 1181、pandas.tseries.offsets.BusinessMonthEnd.is_on_offset方法 1181-1、语法 1181-2、参数 1181-3、功能 1181-4、返回值 1181-5、说明 1181-6、用法 1181-6-1、数据准备 1181-6-2、代码示例 1181-6-3、结果输出 1182、pandas.tseries.offse…

layui table 纵向滚动条导致单元格表头表体错位问题

我用的时layui2.6.8版本 历史项目维护&#xff0c;bug给我让我做了&#xff0c;本来利用前端手段强解决&#xff0c;后来发现很多table 找了解决办法 打开layui-v2.6.8/lay/modules/table.js 如果打开后时压缩的代码 直接搜索 e.find(".layui-table-patch") …

BWO-CNN-BiGRU-Attention白鲸优化算法优化卷积神经网络结合双向门控循环单元时间序列预测,含优化前后对比

BWO-CNN-BiGRU-Attention白鲸优化算法优化卷积神经网络结合双向门控循环单元时间序列预测&#xff0c;含优化前后对比 目录 BWO-CNN-BiGRU-Attention白鲸优化算法优化卷积神经网络结合双向门控循环单元时间序列预测&#xff0c;含优化前后对比预测效果基本介绍模型描述程序设计…

vue.js学习(day 13)

.sync修饰符 App.vue <template><div class"app"><buttonclick"isShow true">退出按钮</button><!-- :visible.sync > :visible update:visible--><BaseDialog :visible.sync"isShow"></BaseDia…

Android复习简答题

一、基础入门 Android程序架构 &#xff08;1&#xff09;app:用于存放程序的代码和资源等内容。包含很多子目录 libs:存放第三方jar包 src/androidTest&#xff1a;存放调试的代码文件 src/main/androidMainfest.xml 整个程序的配置文件&#xff0c;可配置程序所需要的权…