【数据结构】常见排序算法——常见排序介绍、选择排序(直接选择排序、堆排序)交换排序(冒泡排序)

news2024/11/24 5:53:29

文章目录

  • 1.常见排序
  • 2.选择排序
    • 2.1直接选择排序
    • 2.2堆排序
  • 3.交换排序
    • 3.1冒泡排序

1.常见排序

在这里插入图片描述

2.选择排序

  选择排序是一种简单但不高效的排序算法,其基本思想是从待排序的数据中选择最小(或最大)的元素放到已排序的数据末尾。具体操作步骤如下:

(1)找到数据中最小的元素,并把它交换到第一个位置;

(2)在剩下未排序的元素中找到最小的元素,并把它交换到已排序数据的末尾;

(3)重复第2步,直到所有元素都排好序。

  在选择排序的实现中,需要使用两个指针:一个指向当前扫描的区域的起始位置,另一个指向未排序区域的起始位置。通过交换找到每次扫描区域内的最小元素,能够确保每次扫描后已排序区域变大、未排序区域变小。

  选择排序算法的时间复杂度为O(n^2),不适合处理大量数据。

选择排序的基本思想:

  总结:是每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完 。

2.1直接选择排序


直接选择排序的实现思想:

(1)在元素集合array[i]–array[n-1]中选择关键码最大(小)的数据元素;

(2)若它不是这组元素中的最后一个(第一个)元素,则将它与这组元素中的最后一个(第一个)元素交换;

(3)在剩余的array[i]–array[n-2](array[i+1]–array[n-1])集合中,重复上述步骤,直到集合剩余1个元素。

在这里插入图片描述

直接选择排序的实现:

  算法中使用了两个指针left和right,它们分别指向当前待排序区间的左右端点。

  在循环处理待排序区间的时候,算法首先在当前区间中查找最小和最大的元素,使用mini和maxi分别记录这两个位置。

  然后通过交换操作,把最小元素交换到当前待排序区间的最左边,把最大元素交换到最右边。

  最后通过更新left和right的位置来缩小待排序区间的范围,直到排序完成。

  其中Swap函数是一个交换两个整数变量值的函数,实现了传入两个指针并利用中间变量进行交换的操作。

void Swap(int* p1, int* p2)
{
	int tmp = *p1;
	*p1 = *p2;
	*p2 = tmp;
}

void SelectSort(int* a, int n)
{
	int left = 0, right = n - 1;
	while (left < right)
	{
		int mini = left, maxi = left;
		for (int i = left + 1; i <= right; i++)
		{
			if (a[i] < a[mini])
			{
				mini = i;
			}

			if (a[i] > a[maxi])
			{
				maxi = i;
			}
		}

		Swap(&a[left], &a[mini]);
		if (left == maxi)
		{
			maxi = mini;
		}

		Swap(&a[right], &a[maxi]);

		left++;
		right--;
	}
}

直接选择排序的特性总结:

(1)直接选择排序思考非常好理解,但是效率不是很好。实际中很少使用

(2)时间复杂度:O(N^2)

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

(4)稳定性:不稳定

2.2堆排序

  堆排序(Heap Sort)是一种基于堆数据结构的排序算法,它是选择排序的一种优化。堆是一种完全二叉树,分为大根堆和小根堆两种。

  大根堆的定义是,每个结点的值都不大于其父节点的值,根结点是最大值。

  小根堆的定义是,每个结点的值都不小于其父节点的值,根结点是最小值。

堆排序的流程如下:

(1)构建大根堆/小根堆;

(2)将堆顶元素输出,然后将堆重新调整为大根堆/小根堆;

(3)重复步骤2,直到堆中所有元素都已排序。

  具体实现时,可以使用数组来表示堆,对于一个下标为i的结点,其左子节点为2i+1,右子节点为2i+2,其父节点为(i-1)/2。

  堆排序的时间复杂度为O(nlogn),其中n为待排序数组的长度。堆排序是一种原地排序算法,不需要额外的辅助空间,而且由于堆是一种数据结构,可以方便地支持动态的插入和删除操作,因此应用范围比较广泛。

堆排序的实现思想:

  堆排序(Heapsort)是指利用堆积树(堆)这种数据结构所设计的一种排序算法,它是选择排序的一种。它是通过堆来进行选择数据。需要注意的是排升序要建大堆,排降序建小堆。

在这里插入图片描述

堆排序的实现:

  算法中首先需要建立以数组中的元素为节点的大根堆,建堆操作的时间复杂度为O(n)。

  然后,将大根堆中最后一个节点与堆顶元素交换,再重新对交换后的堆进行调整,以使其满足大根堆的性质,并将已排好序的元素一直输出至堆顶,直到所有元素都已排好序。

  具体实现中,利用函数AdjustDown来对堆进行向下调整,以使得当前节点满足大根堆/小根堆的性质。此函数接受三个参数:待调整的堆,堆的长度以及需要调整的节点。在函数中,使用child标记当前节点的左孩子节点,若右孩子节点的值更大,则令child等于右孩子节点的下标;接着判断child和parent的值,若符合堆的性质,则结束调整,否则交换两个节点的值,并向下继续调整。

  在堆排序算法中,最需要注意的是对于任意一个元素,它的左右子树都必须满足大根堆/小根堆的性质。

// 左右子树都是大堆/小堆
void AdjustDown(int* a, int n, int parent)
{
	int child = parent * 2 + 1;
	while (child < n)
	{
		// 选出左右孩子中大的那一个
		if (child + 1 < n && a[child + 1] > a[child])
		{
			++child;
		}

		if (a[child] > a[parent])
		{
			Swap(&a[child], &a[parent]);
			parent = child;
			child = parent * 2 + 1;
		}
		else
		{
			break;
		}
	}
}

void HeapSort(int* a, int n)
{
	// 建堆 -- 向下调整建堆 
	for (int i = (n - 1 - 1) / 2; i >= 0; --i)
	{
		AdjustDown(a, n, i);
	}

	int end = n - 1;
	while (end > 0)
	{
		Swap(&a[end], &a[0]);
		AdjustDown(a, end, 0);

		--end;
	}
}

堆排序的特性总结:

(1)堆排序使用堆来选数,效率就高了很多

(2)时间复杂度:O(N*logN)

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

(4)稳定性:不稳定

3.交换排序

  基本思想:所谓交换,就是根据序列中两个记录键值的比较结果来对换这两个记录在序列中的位置,交换排序的特点是:将键值较大的记录向序列的尾部移动,键值较小的记录向序列的前部移动。

3.1冒泡排序

  冒泡排序(Bubble Sort)是一种简单的排序算法。

  其基本思路是从待排序的第一个元素开始依次比较相邻的两个元素的大小。若前面的元素大于后面的元素,则交换两个元素的位置,这样较大的元素就会像气泡一样不断向上“浮动”,至多经过n-1次排序后就可以将最大的元素放置在最后一个位置上,从而完成第一轮冒泡排序。

  然后,在进行第二轮排序时,对除了最后一个已排好序的元素之外的子序列依次进行冒泡排序,这样第二轮的冒泡排序可以把次大的元素交换到倒数第二个位置。

  以此类推,直到所有元素均已排序完毕。

  冒泡排序算法的平均时间复杂度为 O(n^2),其空间复杂度为O(1),由于其实现简单,代码易懂,因此常用于排序元素较少的列表,对于大规模的数据集,冒泡排序一般不是最优选择。

在这里插入图片描述

冒泡排序的实现:

  算法中使用两重循环,外层循环j控制排序次数,内层循环i控制每一次排序中需要比较的相邻元素位置。

  具体实现中,使用if语句判断相邻元素的大小顺序,并交换这两个元素的位置。

  在排序过程中,待排序的序列不断地缩小,即外层循环的次数逐渐减小,因为每一轮的比较都会让本轮的待比较元素中最大的元素到达本轮的最后位置。因此,当经过n-1轮排序后,整个序列已经有序。

void BubbleSort(int* a, int n)
{
	for (int j = 0; j < n; j++)
	{
		for (int i = 1; i < n - j; i++)
		{
			if (a[i - 1] > a[i])
			{
				Swap(&a[i - 1], &a[i]);
			}
		}
	}
}

冒泡排序的特性总结:

(1)冒泡排序是一种非常容易理解的排序

(2) 时间复杂度:O(N^2)

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

(4)稳定性:稳定

这些就是数据结构中有关直接选择排序、堆排序和冒泡排序的简单介绍了😉
如有错误❌望指正,最后祝大家学习进步✊天天开心✨🎉

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

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

相关文章

可能是 Python 中最火的第三方开源测试框架 pytest

一、介绍 本篇文章是《聊聊 Python 的单元测试框架》的第三篇&#xff0c;前两篇分别介绍了标准库 unittest 和第三方单元测试框架 nose。作为本系列的最后一篇&#xff0c;压轴出场的是Python 世界中最火的第三方单元测试框架&#xff1a;pytest。 pytest 项目地址&#xff1…

预见未来:超强元AI诞生,抓住这个机会,利用AI变现也变得更加容易

目录 一、引言 二、介绍 三、技术展现 四、元AI架构图展现 五、元AI变现技巧—商业版说明 六、后期规划 一、引言 如何利用AI变现已经成为了当今各个行业亟需解决的问题。随着人工智能技术的快速发展和普及&#xff0c;越来越多的企业开始将其应用于产品研发、销售流程优化、客…

一学就会---移除链表相同元素

文章目录 题目描述思路一&#xff1a;思路二&#xff1a; 题目描述 给你一个链表的头节点 head 和一个整数 val &#xff0c;请你删除链表中所有满足 Node.val val 的节点&#xff0c;并返回 新的头节点 。 示例&#xff1a; 思路一&#xff1a; 要移除链表中值为val的结…

Lecture 3 N-gram Language Models

目录 Probabilities: Joint to Conditional 概率&#xff1a;联合概率到条件概率The Markov Assumption 马尔可夫假设Maximum Likelihood Estimation 最大似然估计Book-ending Sequences 序列的开头和结尾Problems with N-gram models N-gram模型的问题Smoothing 平滑处理In Pr…

Mujoco210 Ubuntu 22.04配置安装

.1 下载 1.1 解压 先是下载软件包 然后 mkdir ~/.mujoco缩包所在位置&#xff08;一般在下载目录下&#xff09;在终端打开&#xff0c;输入以下命令将压缩包解压到.mujoco文件夹中&#xff1a; tar -zxvf mujoco210-linux-x86_64.tar.gz -C ~/.mujoco1.2 许可问题 有说mu…

concrt140.dll丢失怎么修复?concrt140.dll丢失的最新修复教程

今天准备打开电脑软件时候&#xff0c;当打开我自己的软件后&#xff0c;弹出了一个对话框&#xff0c;内容是&#xff1a;由于找不到concrt140.dll&#xff0c;无法继续执行代码。重新安装程序可能会解决此问题。 我很纳闷&#xff0c;前几天还好好着呢。于是我上网上查了一下…

八、EGL实践

第一部分基础概念 1&#xff09;引入 之前的OpenGLes应用的开发都是使用类GLSurfaceView &#xff0c;然而GLSurfaceView 是内部已经实现了EGL的封装&#xff0c;也就是对Display&#xff0c;surface&#xff0c;context的管理。因此我们也很方便的利用GLSurfaceView.Rendere…

零基础入门网络安全/Web安全,收藏这一篇就够了

前言 由于我之前写了不少网络安全技术相关的文章和回答&#xff0c;不少读者朋友知道我是从事网络安全相关的工作&#xff0c;于是经常有人私信问我&#xff1a; 我刚入门网络安全&#xff0c;该怎么学&#xff1f;要学哪些东西&#xff1f;有哪些方向&#xff1f;怎么选&…

高频面试八股文用法篇(八) == 和 equals 的区别

目录 区别 如何对equals重写 为何重写equals方法就得重写hashCode方法 扩展延伸 1、使用HashSet存储自定义类对象时为什么要重写equals和hashCode方法&#xff1f; 2、HashMap为什么要同时重写hashCode和equals方法 区别 一、对象类型不同 1、equals()&#xff1a;是超类…

第二章:MySQL环境搭建

第二章&#xff1a;MySQL环境搭建 2.1&#xff1a;MySQL的下载、安装、配置 MySQL的四大版本 MySQL Community Server社区版本&#xff1a;开源免费、自由下载&#xff0c;但不提供官方技术支持&#xff0c;适用于大多数普通用户。MySQL Enterprise Edition企业版本&#xff1…

SpringBoot个人博客系统(含源码+数据库)

一、作品设计理念 个人博客系统是一个让个人可以通过互联网自由表达、交流和分享的平台&#xff0c;是个人展示自己思想、感受和经验的品牌。设计理念对于任何一个个人博客系统来说都非常重要&#xff0c;它直接影响到用户的使用体验和网站的整体感觉。 好的设计理念应该着眼于…

小红书热搜榜TOP1,多巴胺时尚爆火,怎么抄作业?

今夏时尚&#xff0c;明媚与简约并存。要说今年夏天什么最火&#xff1f;多巴胺必须拥有姓名。无论男女、老少、人宠&#xff0c;都被这股快乐风带飞。 “多巴胺”有多火&#xff1f;就只是彩色穿搭吗&#xff1f;各大博主、品牌若想加入&#xff0c;要怎么玩&#xff1f;今儿&…

Python如何解决“京东滑块验证码”(5)

前言 本文是该专栏的第51篇,后面会持续分享python爬虫干货知识,记得关注。 多数情况下使用模拟登录会遇到滑块验证码的问题,对于普通的滑块验证码,使用selenium可以轻松解决。但是对于滑块缺失验证码,比如京东的滑块验证要怎么解决呢?京东滑块验证的这个滑块缺口,每次刷…

软件测试报告模板范文来了——优秀测试报告模板流程

一、软件测试报告是什么&#xff1f; 软件测试报告就是当软件开发人员开发出软件之后&#xff0c;在上市前交由测试人员进行一系列测试&#xff0c;再由测试人员对过程和结果的进行记录分析的一份文档。也是测试团队的工作成果展现&#xff0c;通过详细的记录测试内容&#xf…

算法修炼之筑基篇——筑基二层中期(讨论一下如何解决动态方程问题,没时间了,快快快看一下)

✨博主&#xff1a;命运之光 &#x1f984;专栏&#xff1a;算法修炼之练气篇 &#x1f353;专栏&#xff1a;算法修炼之筑基篇 ✨博主的其他文章&#xff1a;点击进入博主的主页 前言&#xff1a;学习了算法修炼之练气篇想必各位蒟蒻们的基础已经非常的扎实了&#xff0c;下来…

使用FFmpeg实现最简单的视频播放

按照之前的编译步骤我们会编译得到使用ffmpeg需要的文件&#xff0c;现在就使用ffmpeg实现最简单的视频播放 集成ffmpeg 使用Android Studio创建一个Native C项目编译之后得到三个文件夹 把include 文件夹放到cpp目录下面。 main 目录下面新建jniLibs 目录把lib文件下的so文件…

Java之BigDecimal使用

Java之BigDecimal使用 1、BigDecimal概述 ​ BigDecimal用来对超过16位有效位的数进行精确的运算。双精度浮点型变量double可以处理16位有效数&#xff0c;但在实际应用中&#xff0c;可能需要对更大或者更小的数进行运算和处理。一般情况下&#xff0c;对于那些不需要准确计…

OA系统,企业数字化转型的重要工具,用现成还是自己搭建呢

什么是OA系统 OA系统是办公自动化系统的简称&#xff0c;它是指一种基于计算机技术的办公工作管理系统&#xff0c;用于协调和规划企业内部各部门的信息发布、通信、人员流动、文档管理等方面的工作。它可以有效地提高企业办公效率和工作效益&#xff0c;优化企业内部沟通协作…

计算机视觉 | 深度学习预训练与MMPretrain

前言 MMPretrain是一款基于pytorch的开源深度学习预训练工具箱&#xff0c;是OenMMLab的项目成员之一。它是一个全新升级的预训练开源算法框架&#xff0c;旨在提供各种强大的预训练主干网络&#xff0c;并支持了不同的预训练策略。 一、MMPretrain算法库介绍 MMPretrain 源…

几分钟上线一个应用,这个神器我爱了!

配置一套公司企业运用的SaaS工作流办公管理系统需要多久&#xff1f;需要多少人才能开发出来&#xff1f;传统软件开发起码需要10个人&#xff0c;花上个把月时间&#xff0c;才能做出一套比较完整的SaaS工作流办公管理系统。 传统的开发模式它需要前后端程序员以及各平台系统的…