选择排序(直接选择排序与堆排序的比较)

news2024/9/20 3:21:37

选择排序

选择排序时间复杂度

1. 直接选择排序思考⾮常好理解,但是效率不是很好。实际中很少使用,思路是先进行遍历找到元最小的元素,然后与第一个进行交换     

2. 时间复杂度:O(n^{2}

3. 空间复杂度:O(1)

选择排序源码

void SelectSort(int* arr, int n)
{
	for (int i = 0; i < n; i++)
	{
		int min = i;
		for (int j = i + 1; j < n; j++)
		{
			if (arr[min] > arr[j])
			{
				min = j;
			}
		}
		swap(&arr[i], &arr[min]);
	}
}

上述代码的时间复杂度为:O(n^{2}),但是不是最完美的所以我们进行优化一下,但是优化后时间复杂度还是O(n^{2})。 这时就可以看出选择排序和冒泡排序的差别,冒泡排序优化后时间复杂度会进行改变但是选择排序就并不会改变。

优化后的选择排序

堆排序

堆排序的分析

堆排序分为大根堆和小根堆两种方法,这两种方法主要区别的是升序还是降序。升序大根堆因为我们知道大根堆中最大位于堆顶的,经过最后一个与堆顶进行替换后最大元素会被换到后面,堆排序是基于数组的所以数值是逐渐增大的。同理分析(降序是小根堆)。

堆排序的时间复杂度

堆排序的时间复杂度要计算建堆的时间与置换的时间,以向下建堆排序为准:O(n + n ∗ log n) ,即O(n log n)。

向上建堆时间复杂度为:O(n ∗ log2 n)

向上调整的证明分析

向下建堆的时间复杂度为:O(n)

向下调整证明的分析

源代码

HeadSort.c

void swap(int* n, int* m)
{
	int tmp = *n;
	*n = *m;
	*m = tmp;
}
//向下调整
void HeapDown(int* arr, int parent, int n)
{
	//向下排序要注意是父节点与子节点两个中最小的进行比较
	//要限制child+1<n
	int child = 2 * parent + 1;
	//小堆排序
	//用child小于
	while (child < n)
	{
		if (child + 1 < n && arr[child] > arr[child + 1])
		{
			//找到最小的节点,从而和父节点进行交换
			child++;
		}
		if (arr[child] < arr[parent])
		{
			swap(&arr[child], &arr[parent]);
			parent = child;
			child = 2 * parent + 1;
		}
		else
		{
			break;
		}
	}
}

 test.c

#include"HeapSort.h"
void HeapSort(int* arr, int n)
{
	//建堆
    // a数组直接建堆 O(N)
     for (int i = (n-1-1)/2; i >= 0; --i)
     {
         HeapDown(arr, i, n);
     }
    // O(N*logN)
	//升序---大堆
	//降序----小堆
	//循环将堆顶数据跟最后位置(会变化,每次减少一个数据)的数据进行交换
	int end = n - 1;
	//取堆顶返回的是堆的数据结构,而不是数组,其次也是用堆顶进行覆盖原来数据
	//所以使用了堆顶与堆尾的向下调整,并且每次让end--
	while (end > 0)
	{
		swap(&arr[0], &arr[end]);
		HeapDown(arr, 0, end);
		end--;
	}
    //打印
    for (int i = 0; i < n; i++)
    {
	    {
	       	printf("%d ", arr[i]);
	    }
    }
}
int main()
{
	int arr[] = { 1,2,3,4,5,6 };
	HeapSort(arr, 6);
}

快速排序

快速排序是Hoare于1962年提出的⼀种⼆叉树结构的交换排序⽅法,其基本思想为:任取待排序元素 序列中的某元素作为基准值,按照该排序码将待排序集合分割成两⼦序列,左⼦序列中所有元素均⼩ 于基准值,右⼦序列中所有元素均⼤于基准值,然后最左右⼦序列重复该过程,直到所有元素都排列 在相应位置上为⽌

快排的示意图
快排的解题思路

快速排序中部分细节分析

快速排序的细节较多主要在一下两个部分。

1.left <= right?这种情况是为了预防相遇值的精度大于精准值,这样若进行替换就会造成错误的交换方式。

2.arr[right] > arr[base]?

 这种情况主要是为了防止,出现相同数据造成时间复杂多过高,最好就是在递归是把一个大的队列分为大小相同的两个,然后在进行递归。

递归时的判断条件

快排特性

时间复杂度为 0(n log n)、自适应排序:在平均情况下,哨兵划分的递归层数为 log n ,每层中的总循 环数为n ,总体使用0(n log n)时间。在最差情况下,每轮哨兵划分操作都将长度为n 的数组划分为 长度为 0 和 n−1 的两个子数组,此时递归层数达到 n ,每层中的循环数为 n ,总体使用 0(n^{2}) 时间。

空间复杂度为 0(n )、原地排序:在输入数组完全倒序的情况下,达到最差递归深度 n,使用 0(n )栈 帧空间。排序操作是在原数组上进行的,未借助额外数组。

非稳定排序:在哨兵划分的最后一步,基准数可能会被交换至相等元素的右侧。

快排的优点

从名称上就能看出,快速排序在效率方面应该具有一定的优势。尽管快速排序的平均时间复杂度与“归并排 序”和“堆排序”相同,但通常快速排序的效率更高,主要有以下原因。

出现最差情况的概率很低:虽然快速排序的最差时间复杂度为 0(n^{2}) ,没有归并排序稳定,但在绝大 多数情况下,快速排序能在 0(n log n) 的时间复杂度下运行。

缓存使用效率高:在执行哨兵划分操作时,系统可将整个子数组加载到缓存,因此访问元素的效率较 高。而像“堆排序”这类算法需要跳跃式访问元素,从而缺乏这一特性。

复杂度的常数系数小:在上述三种算法中,快速排序的比较、赋值、交换等操作的总数量最少。这与 “插入排序”比“冒泡排序”更快的原因类似。

快排源码

//快速排序
void swap(int* n, int* m)
{
	int temp = *n;
	*n = *m;
	*m = temp;
}
int _QuickSort(int* arr, int left, int right)
{
	int base = left;
	left++;
	while (left<=right)
	{
		while (left <= right && arr[right] > arr[base])
		{
			right--;
		}
		while (left <= right && arr[left] < arr[base])
		{
			left++;
		}
		if (left <= right)
		{
			//隐藏细节
			swap(&arr[left++], &arr[right--]);
		}
	}
	//此时已经不满足,left<=right这时候把right和关键值进行置换

	swap(&arr[base], &arr[right]);
	return right;
}
void QuickSort(int* arr, int left, int right)
{
	if (left >= right)
	{
		return;
	}
	//[left,right]--->找基准值mid
	int keyi = _QuickSort(arr, left, right);
	//左子序列:[left,keyi-1]
	QuickSort(arr, left, keyi - 1);
	//右子序列:[keyi+1,right]
	QuickSort(arr, keyi + 1, right);
}

总结

以上就是本次总结,其中快排的坑还是较多的,需要认真分析一下,最后创作不易,希望各位大佬能一键三连(点赞,收藏,关注)。

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

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

相关文章

gmapping算法核心部分

processScan函数 参考&#xff1a;https://blog.csdn.net/CV_Autobot/article/details/131058981 drawFromMotion:根据运动模型更新粒子位姿 scanMatch:进行扫描匹配 resample:重采样 逐步分解并详细解释代码 1. 获取当前扫描的相对位姿 OrientedPoint relPose reading.…

舜宇光学科技社招校招入职测评:商业推理测验真题汇总、答题要求、高分技巧

舜宇光学科技&#xff08;集团&#xff09;有限公司&#xff0c;成立于1984年&#xff0c;是全球领先的综合光学零件及产品制造商。2007年在香港联交所主板上市&#xff0c;股票代码2382.HK。公司专注于光学产品的设计、研发、生产及销售&#xff0c;产品广泛应用于手机、汽车、…

BEM架构

视频 总结&#xff1a; BEM架构&#xff1a;一个命名类的规范而已&#xff0c;说白了就是如何给类起名字使用sass的目的&#xff1a;在<style>中模块化的使用类名&#xff0c;同时减少代码数量 1、 BEM架构 &#xff08;通义灵码查询结果&#xff09; BEM (Block Ele…

【hot100篇-python刷题记录】【和为 K 的子数组】

R5-子串篇 目录 思路&#xff1a; 优化&#xff1a; tip: 代码&#xff1a; 结果&#xff1a; ps: 思路&#xff1a; 滑动&#xff0c;应该可以使用滑动窗口来解题。 貌似前缀和也可以&#xff0c;left&#xff0c;right两个指针&#xff0c;right的前缀和-left的前缀…

【学习笔记】printf中%m的含义

【学习笔记】printf中%m的含义 在有些代码中会看到如下的写法&#xff1a; printf("%m\n");printf中使用了%m来打印输出&#xff0c;那么%m又是什么意思呢&#xff1f; 其实%m 并不是在所有的 printf 实现中都通用或标准化的选项&#xff0c;而是在某些特定的编程语…

vue的markdown编辑器插件比对

vue的markdown编辑器插件比对 文章说明md-editor-v3的使用及效果展示vditor的使用及效果展示 文章说明 文章比对 md-editor-v3、vditor 这两个插件的使用及效果体验 md-editor-v3的使用及效果展示 安装 npm install md-editor-v3使用 <script setup> import {reactive} f…

图神经网络(Graph Neural Networks)是什么?

图神经网络&#xff08;Graph Neural Networks&#xff09;是什么&#xff1f; 引言 在数据科学和机器学习的广阔领域中&#xff0c;图结构数据以其独特的复杂性和丰富性成为了一个重要的研究方向。从社交网络中的用户关系&#xff0c;到生物信息学中的蛋白质交互网络&#x…

跨进程通信使用 Zenoh中间件 进行高效数据传输的测试和分析

文章目录 1. 引言2. Zenoh C 使用指南2.1 安装 Zenoh C 库2.2 编写基本的 Zenoh C 程序订阅示例发布示例 2.3 编译和运行程序 3. Zenoh 与 ROS2 集成3.1 安装 Zenoh3.2 安装 ROS2 的 Zenoh RMW 实现3.3 设置 RMW 实现为 Zenoh3.4 验证配置 4. 编写基于 Zenoh 的 ROS2 应用程序4…

Linux系统编程 --- 多线程

线程&#xff1a;是进程内的一个执行分支&#xff0c;线程的执行粒度&#xff0c;要比进程要细。 一、线程的概念 1、Linux中线程该如何理解 地址空间就是进程的资源窗口。 在一个程序里的一个执行路线就叫做线程&#xff08;thread&#xff09;。更准确的定义是&#xff1…

浏览器遇到的问题

下载的时候遇到&#xff0c;需要授权&#xff0c;无法下下载 将隐私里面的全部关掉

虚幻5|AI巡逻宠物伴随及定点巡逻—初步篇

一.建立AI基本三件套 1.建立AI基本三件套 二.使用AI的基本设置 1.打开我们想要用的AI宠物的蓝图&#xff0c;选中自我Actor,右侧细节处找到AI&#xff0c;选中对应的AI控制器 三.打开AI控制器 写如下 四&#xff0c;AI行为树 1.新建一个任务&#xff0c;命名含巡逻二字即可…

BigInteger与BigDecimal

BigInteger BigInteger构造方法 public BigInteger(int num, Random rnd) 获取随机大整数&#xff0c;范围&#xff1a;[0 ~ 2的num次方-1] public BigInteger(String val) 获取指定的大整数 public BigInteger(String val, int radix) 获取指定进制的大整数 构造方法小结…

Power Query抓取多页数据导入到Excel

原文链接 举例网站&#xff1a;http://vip.stock.finance.sina.com.cn/q/go.php/vLHBData/kind/ggtj/index.phtml?last5&p1 操作步骤 &#xff08;版本为&#xff1a;Excel2010&#xff09;&#xff1a; Step-01&#xff1a;单击【Power Query】-【从Web】&#xff0c;…

Java之文件操作和IO

目录 File类 属性 构造方法 方法 文件内容的读写 InputStream OutputStream File类 属性 修饰符及类型属性说明static StringpathSeparator依赖于系统的路径分隔符&#xff0c;String类型的表示static charpathSeparator依赖于系统的路径分隔符&#xff0c;char类型的…

ps磨皮滤镜插件Imagenomic Portraiture 4.5 Build 4501中文版

PS磨皮神器更新为Portraiture 中文汉化版&#xff08;支持PS 2024&#xff09; 。Portraiture 4.5 Build 4501中文绿色破解版是一款非常强大的适用于Photoshop&#xff0c;Lightroom&#xff0c;Aperture的人物磨皮&#xff08;人物润色&#xff09;插件。Portraiture插件被经常…

基于eBPF的procstat软件追踪C++ STL容器扩容

在性能敏感的C程序中&#xff0c;标准模板库&#xff08;STL&#xff09;容器的扩容操作往往是导致性能抖动的原因之一。扩容操作可能会引发内存重新分配和数据迁移&#xff0c;从而导致性能不稳定。然而&#xff0c;由于C标准库的扩容函数通常被内联化&#xff0c;传统的方法难…

Geekbench AI 1.0正式发布:AI性能评估

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

STM32标准库学习笔记-4.定时器中断

参考教程&#xff1a;【STM32入门教程-2023版 细致讲解 中文字幕】 定时器简介 TIM&#xff08;Timer&#xff09;定时器。定时器可以对输入的时钟进行计数&#xff0c;并在计数值达到设定值时触发中断。16位计数器、预分频器、自动重装寄存器的时基单元&#xff0c;在72MHz计…

vue3响应式工具 toRefs() 和 toRef()

前言 直接解构响应式对象的属性进行赋值给新的变量&#xff0c;会导致新变量失去响应式。 当修改新变量的值时&#xff0c;不会触发原始响应式对象的更新&#xff0c;从而在模板中也不会有相应的视图更新。 示例&#xff1a; <template><div><p>姓名: {{ …

垂直行业数字化表现抢眼 亚信科技全年利润展望乐观

大数据产业创新服务媒体 ——聚焦数据 改变商业 2024年8月14日&#xff0c;亚信科技控股有限公司&#xff08;股票代码&#xff1a;01675.HK&#xff09;公布了公司截至2024年6月30日的中期业绩。 财报数据显示&#xff0c;2024年上半年&#xff0c;亚信科技的营业收入为人民币…