数据结构-C语言-排序(2)

        代码位置:test-c-2024: 对C语言习题代码的练习 (gitee.com)

一、前言:

1.1-排序定义:

排序就是将一组杂乱无章的数据按照一定的规律(升序或降序)组织起来。(注:我们这里的排序采用的都为升序)

1.2-排序分类:

常见的排序算法:
  • 插入排序
    a. 直接插入排序
    b. 希尔排序

  • 选择排序
    a. 选择排序
    b. 堆排序
  • 交换排序
    a. 冒泡排序
    b. 快速排序
  • 归并排序
    a. 归并排序
  • 非比较排序
    a.计数排序
    b.基数排序

1.3-算法比较:

1.4-目的:

        今天,我们这里要实现的是选择排序、堆排序、冒泡排序

二、选择排序:

2.1-思路:

        1.找到数组中最小的元素,拎出来,将它和数组的第一个元素交换位置;

        2.找到数组中最大的元素,拎出来,将它和数组的最后一个元素交换位置;        

        3.在剩下的元素中继续寻找最小的元素,拎出来,和数组的第二个元素交换位置;

        4.在剩下的元素中继续寻找最大的元素,拎出来,和数组的倒数第二个元素交换位置;

        5.需要注意max若与left位置相同时需特殊处理,否则位置交换会出现问题;

        6.如此循环,直到整个数组排序完成;

        7.若是由大到小也是同样方法,只需要修改比较大小的符号;

2.2-过程图:

2.3-代码:


//升序
void SelectSort(int* a, int len)			//选择排序---时间复杂度(O(N^2))
{
	printf("原数组顺序:");
	for (int i = 0; i < len; i++)
	{
		printf("%d  ", a[i]);
	}
	printf("\n");
	int left = 0;
	int right = len - 1;

	int max = 0;
	int min = 0;
	while (left < right)
	{
		max = min = left;
		for (int i=left; i<=right; i++)
		{
			if (a[i] > a[max])
				max = i;
			if (a[i] < a[min])
				min = i;
		}
		Swap(&a[left], &a[min]);
		if (max == left)
		{
			max = min;
		}
		Swap(&a[right], &a[max]);
		++left;
		right--;
		printf("第%d时排序:",left);
		for (int i = 0; i < len; i++)
		{
			printf("%d  ", a[i]);
		}
		printf("\n");
	}
	
}

2.4-效果图:

2.5-性质:

由上述代码及图片见:

时间复杂度:

        简单选择排序是通过两层循环实现。 第一层循环:依次遍历序列当中的每一个元素 第二层循环:将遍历得到的当前元素依次与余下的元素进行比较,符合最小元素的条件,则交换。每次循环时间复杂度都为O(N)所以选择排序时间复杂度为O(N^2)

空间复杂度:

        因为没开辟空间,所以空间复杂度为O(1)。

稳定性:

        选择排序是一种不稳定的排序算法。 我们可以从上面的图片中看出,选择排序每次都要找剩余未排序元素中的最小值,并和前面的元素交换位置,这样破坏了稳定性。 比如说:5,8,5,2,9 这样一组数据,使用选择排序算法来排序的话,第一次找到最小元素 2,与第一个 5 交换位置,那第一个 5 和中间的 5 顺序就变了,所以选择排序是不稳定的排序算法

三、堆排序:

3.1-思路:

        对于堆排序,我们首先要将无序的数组建成大堆,大堆的话有助于排升序。因为大堆可以确定最大值,我们只需将首元素与尾元素交换,然后去除尾元素,继续进行向下调整,最后进行循环,直到排序完成为止。

3.2-过程图:

3.3-代码:


void AdjustDown(int* a, int len, int parent)			//向下调整---时间复杂度(O(logN))
{
	int child = parent * 2 + 1;

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

void HeapSort(int* a, int len)			//堆排序---时间复杂度(O(N*logN))
{
	printf("原数组顺序:");
	for (int i = 0; i < len; i++)
	{
		printf("%d  ", a[i]);
	}
	printf("\n");
	//建大堆---时间复杂度(O(N))
	for (int i = (len - 1 - 1) / 2; i >= 0; i--)
	{
		AdjustDown(a, len, i);
	}
	printf("建堆后数组顺序:");
	for (int i = 0; i < len; i++)
	{
		printf("%d  ", a[i]);
	}
	printf("\n");
	//自我实现排序---时间复杂度(O(N*logN))
	int end = len-1;
	int n = 1;
	while(end>0)
	{
		Swap(&a[0], &a[end]);
		AdjustDown(a, end, 0);
		--end;
		
		printf("第%d趟排序:",n++);
		for (int i = 0; i < len; i++)
		{
			printf("%d  ", a[i]);
		}
		printf("\n");
	}

}

3.4-效果图:

3.5-性质:

时间复杂度:

        由于向下调整函数的时间复杂度为O(logN),遍历数组的时间复杂度为O(N),所以堆排序的时间复杂度为O(N*logN)

空间复杂度:

        因为没开辟空间,所以空间复杂度为O(1)。

稳定性:

        堆排序是通过反复调整元素位置来完成排序的过程,其中涉及到交换操作。这些交换操作可能导致相同键值元素的相对顺序发生变化,因此堆排序是一个不稳定的排序算法

四、冒泡排序:

4.1-思路:

        通过对待排序序列从前向后(从下标较小的元素开始),依次对相邻两个元素的值进行两两比较,若发现逆序则交换,使值较大的元素逐渐从前移向后部,就如果水底下的气泡一样逐渐向上冒。

4.2-过程图:

4.3-代码:


void BubbleSort(int* a, int len)			//冒泡排序---时间复杂度(O(N^2))
{
	printf("原数组顺序:");
	for (int i = 0; i < len; i++)
	{
		printf("%d  ", a[i]);
	}
	printf("\n");
	for (int j = 0; j < len - 1; j++)
	{
		int judge = 1;		//判断数组是否有序
		for (int i = 0; i < len - j-1; i++)
		{
			if (a[i] > a[i + 1])		
			{
				Swap(&a[i], &a[i + 1]);
				judge = 0;		//如果进循环说明无序令judge为0
			}
		}
		printf("第%d趟排序:", j + 1);
		for (int i = 0; i < len; i++)
		{
			printf("%d  ", a[i]);
		}
		printf("\n");
		if (judge)
		{
			return;
		}
		
	}
	
}

4.4-效果图:

4.5-性质:

时间复杂度:

        冒泡排序算法是一种基于比较的排序算法,每次冒泡过程,都会有一个数据确定位置。最坏的情况下需经过n-1次冒泡,就有n个数据确定了位置时间复杂度为O(N^2),但若是我们加入判断条件则最好的情况下可提前结束循环最好的情况下只需经过2次冒泡即可此时时间复杂度为O(N)

空间复杂度:

        因为没开辟空间,所以空间复杂度为O(1)。

稳定性:

        冒泡排序是相邻元素之间的比较,此时我们可以控制相同元素的位置,所以冒泡排序是稳定性的算法。

五、结语:

        上述内容,即是我个人对数据结构排序中选择排序、堆排序、冒泡排序的个人见解以及自我实现。若有大佬发现哪里有问题可以私信或评论指教一下我这个小萌新。非常感谢各位友友们的点赞,关注,收藏与支持,我会更加努力的学习编程语言,还望各位多多关照,让我们一起进步吧!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2-36 基于matlab的流行学习算法程序

基于matlab的流行学习算法程序。通过GUI的形式将MDS、PCA、ISOMAP、LLE、Hessian LLE、Laplacian、Dissusion MAP、LTSA八种算法。程序以可视化界面进行展示&#xff0c;可直接调用进行分析。多种案例举例说明八种方法优劣&#xff0c;并且可设置自己数据进行分析。程序已调通&…

STM32智能工业自动化监控系统教程

目录 引言环境准备智能工业自动化监控系统基础代码实现&#xff1a;实现智能工业自动化监控系统 4.1 数据采集模块 4.2 数据处理与控制模块 4.3 通信与网络系统实现 4.4 用户界面与数据可视化应用场景&#xff1a;工业自动化与管理问题解决方案与优化收尾与总结 1. 引言 智能…

百度人脸识别Windows C++离线sdk C#接入

百度人脸识别Windows C离线sdk C#接入 目录 说明 设计背景 • 场景特点&#xff1a; • 客户特点&#xff1a; • 核心需求&#xff1a; SDK 包结构 效果 代码 说明 自己根据SDK封装了动态库&#xff0c;然后C#调用。 功能接口 设计背景 • 场景特点&#xff1a; -…

【漏洞复现】深信服 行为感知系统 日志中心 c.php 远程命令执行

免责声明&#xff1a; 本文内容旨在提供有关特定漏洞或安全漏洞的信息&#xff0c;以帮助用户更好地了解可能存在的风险。公布此类信息的目的在于促进网络安全意识和技术进步&#xff0c;并非出于任何恶意目的。阅读者应该明白&#xff0c;在利用本文提到的漏洞信息或进行相关测…

PTA - 嵌套列表求和

使用递归函数对嵌套列表求和 函数接口定义&#xff1a; def sumtree(L) L是输入的嵌套列表。 裁判测试程序样例&#xff1a; /* 请在这里填写答案 */L eval(input()) print(sumtree(L)) # 调用函数 输入样例&#xff1a; 在这里给出一组输入。例如&#xff1a; [1,[2…

PriorityQueue 阅读记录

1、前言 1、优先队列&#xff0c;底层通过数组来构造树&#xff08;二叉树) 来实现的。 2、默认是最小堆&#xff08;取出来的是最小值)&#xff0c;可以通过传入一个比较器 comparator 来构造一个最大堆。 3、传入的参数不能为空&#xff0c;否则抛出NPE问题。 4、最大堆的…

系统架构设计师教程 第3章 信息系统基础知识-3.1 信息系统概述

系统架构设计师教程 第3章 信息系统基础知识-3.1 信息系统概述 3.1.1 信息系统的定义3.1.1.1 信息系统3.1.1.2 信息化3.1.2 信息系统的发展3.1.2.1 初始阶段3.1.2.2 传播阶段3.1.2.3 控制阶段3.1.2.4 集成阶段3.1.2.5 数据管理阶段3.1.2.6 成熟阶段3.1.3 信息系统的分类3.…

读人工智能全传15意向立场

1. 物理立场 1.1. 可以解释一个实体行为 1.2. 在物理立场中&#xff0c;我们使用自然法则(物理、化学等)来预测系统的行为结果 1.3. 虽然物理立场在解释这种行为的时候非常有效&#xff0c;但无法应用于理解或者预测人类行为 1.3.1. …

六边形动态特效404单页HTML源码

源码介绍 动态悬浮的六边形,旁边404文字以及跳转按钮,整体看着像科技二次元画风,页面简约美观,可以做网站错误页或者丢失页面,将下面的代码放到空白的HTML里面,然后上传到服务器里面,设置好重定向即可 效果预览 完整源码 <!DOCTYPE html> <html><head…

关于springboot的@DS(““)多数据源的注解无法生效的原因

对于com.baomidou.dynamic.datasource.annotation的DS注解&#xff0c;但凡有一个AOP的修改都会影响到多数据源无法生效的问题&#xff0c;本次我是添加了方法上添加了Transactional&#xff0c;例如下图&#xff1a; 在方法上写了这个注解&#xff0c;会影响到DS("db2&qu…

万字长文之分库分表里如何优化分页查询?【后端面试题 | 中间件 | 数据库 | MySQL | 分库分表 | 分页查询】

分库分表的一般做法 一般会使用三种算法&#xff1a; 哈希分库分表&#xff1a;根据分库分表键算出一个哈希值&#xff0c;根据这个哈希值选择一个数据库。最常见的就是数字类型的字段作为分库分表键&#xff0c;然后取余。比如在订单表里&#xff0c;可以按照买家的ID除以8的…

【PB案例学习笔记】-32制作一个简单记事本程序

大家好&#xff0c;我是晓凡。 写在前面 这是PB案例学习笔记系列文章的第32篇&#xff0c;该系列文章适合具有一定PB基础的读者。 通过一个个由浅入深的编程实战案例学习&#xff0c;提高编程技巧&#xff0c;以保证小伙伴们能应付公司的各种开发需求。 文章中设计到的源码…

Web3D:WebGL为什么在渲染性能上输给了WebGPU。

WebGL已经成为了web3D的标配&#xff0c;市面上有N多基于webGL的3D引擎&#xff0c;WebGPU作为挑战者&#xff0c;在渲染性能上确实改过webGL一头&#xff0c;由于起步较晚&#xff0c;想通过这个优势加持&#xff0c;赶上并超越webGL仍需时日。 贝格前端工场为大家分享一下这…

leetcode 1459 矩形面积(postgresql)

需求 表: Points ---------------------- | Column Name | Type | ---------------------- | id | int | | x_value | int | | y_value | int | ---------------------- id 是该表主键 每个点都用二维坐标 (x_value, y_value) 表示 写一个 SQL 语句&#xff0c;报告由表中任…

Redis-基础概念

目录 概念 Redis是什么 Redis 和 MySQL 的区别&#xff1f; Redis单线程有什么极端场景的瓶颈 Redis为什么快? 为什么Redis是单线程? Redis是单线程还是多线程 Redis为什么选择单线程做核心处理 Redis6.0之后引入了多线程&#xff0c;你知道为什么吗? 瓶颈是内存和I…

MySQL-事务、日志

事务 特性 原子性 是指事务开始后&#xff0c;必须成功执行完所有的操作才会结束&#xff0c;否则会回滚到事务刚开始前。 拿转账来说&#xff0c;一个成功的 A向B转账100元的过程 会涉及如下过程&#xff1a; A&#xff1a;从数据库读取A的余额&#xff1b;A的余额-100&am…

Pytorch学习笔记day1—— 安装教程

这里写自定义目录标题 Pytorch安装方式 工作需要&#xff0c;最近开始搞一点AI的事情。但是这个国产的AI框架&#xff0c;实话说对初学者不太友好 https://www.mindspore.cn/ 比如说它不支持win下的CUDA&#xff0c;可是我手里只有3070Ti和4060也不太可能自己去买昇腾就有点绷不…

C. Alternating Subsequence[双指针,贪心]

题目描述&#xff1a; 思路分析&#xff1a;题目俩要求&#xff0c;最长&#xff0c;值最大&#xff0c;异号&#xff0c;保证异号的情况是找到最长而且尽可能大&#xff0c;其实很容易想到&#xff0c;一开始先把第一个数单独放进去&#xff0c;保证不浪费任何一个元素&#…

迈克尔的44岁:时间的感悟与人生的智慧

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

【JavaEE】HTTP(2)

&#x1f921;&#x1f921;&#x1f921;个人主页&#x1f921;&#x1f921;&#x1f921; &#x1f921;&#x1f921;&#x1f921;JavaEE专栏&#x1f921;&#x1f921;&#x1f921; &#x1f921;&#x1f921;&#x1f921;下一篇文章&#xff1a;【JavaEE】HTTP协议(…