十种排序算法(2) - 代码和原理

news2024/11/27 12:48:46

本文建立在上一篇文章的基础上:《十种排序算法(1) - 准备工具》

注:本文以升序为例子进行实现和解释

1.选择排序

选择排序是最简单几种排序算法之一

(1) 原理

不断使用查找并选择最小的元素放到数组的首端
请添加图片描述

(2) 复杂度分析

  • 最好:O(n^2)
  • 最坏:O(n^2)
  • 平均:O(n^2)
  • 空间复杂度:O(1)
  • 稳定:否
    在这里插入图片描述

在这里插入图片描述

(3) 实现

//选择排序 O(n^2)
inline void selectionSort(int* nums, int numsSize)
{
	for (int i = 0; i < numsSize - 1; i++)
	{
		int minIndex = i;
		for (int a = i ; a < numsSize; a++)
		{
			minIndex = nums[a] < nums[minIndex] ? a : minIndex;
		}
		if (minIndex != i) swap(&nums[i], &nums[minIndex]);
	}
}

2.冒泡排序

冒泡排序是最简单的几种排序算法之一

(1) 原理

重复遍历数组,每次都比较nums[i]和nums[i+1]的大小,如果前者大于后者则交换,如果此次遍历无交换,可以立刻结束排序过程。
请添加图片描述
形象的理解可以理解成气泡在水中冒出的过程。

(2) 复杂度分析

  • 最好:O(n) - 当数组本身已经是排序好的状态时,冒泡排序只需要进行一轮遍历即可确认数组有序
  • 最坏:O(n^2) - 当数组是逆序排列时,冒泡排序需要进行最大数量级的比较和交换。
  • 平均:O(n^2)
  • 空间复杂度:O(1)
  • 稳定:是
    在这里插入图片描述
    在这里插入图片描述
    可以看到冒泡排序的时间复杂度与选择排序相同,但是时间差距巨大。主要原因是操作类型的不同,选择排序有更少的交换次数。而比较次数上,二者相差不大,

冒泡排序往往在数据本身就大部分有序的时候有良好的表现,其耗时取决于数据本身的逆序度,而本测试程序取随机值,数据无序度一般相当高。冒泡排序在数据完全有序时仅为O(n),而在数据完全逆序时,退化为O(n2)

(3)实现

inline void bubbleSort(int* nums, int numsSize)
{
	//i为有序元素个数
	for (int i = 0; i < numsSize - 2; i++)
	{
		int swapCount = 0;
		for (int x = 0; x < numsSize - i - 1; x++)
		{
			if (nums[x] > nums[x + 1])
			{
				swap(&nums[x], &nums[x + 1]);
	![请添加图片描述](https://img-blog.csdnimg.cn/fe86f66fb3cb4b39b0498002d8a0646a.gif)
			swapCount++;
			}
		}
		if (!swapCount) break;
	}
}

3.直接插入排序

(1)原理

遍历数组,在当前元素之前(认为之前已经有序)找到合适的位置进行插入。
请添加图片描述

(2)复杂度分析

  • 最好:O(n) - 当数组本身已经是基本有序时,插入排序只需要进行少量的比较和移动
  • 最坏:O(n^2) - 当数组是逆序排列时,插入排序需要进行最大数量级的比较和移动。
  • 平均:O(n^2)
  • 空间复杂度:O(1)
  • 稳定:是
    在这里插入图片描述
    在这里插入图片描述
    插入排序同样是在部分有序时表现很好

4.希尔排序

(1)原理

请添加图片描述
希尔排序是对插入排序的优化,是一个多阶段排序算法,它通过改变增量序列,对数据进行多轮排序,逐渐减少增量,最终完成排序。由于最开始的排序阶段会进行远距离的交换,因此可以更快地消除逆序对,使得后续的插入排序阶段所需的移动次数大大减少。

希尔建议的增量为 numSize / (2n),但是这并非最优解,根据数据规模和规律的不同选取不同的增量会有更佳的效果,可以根据使用情景查阅。

(2)复杂度分析

  • 最好:取决于增量序列的选择,通常为 O(n log^2 n) 或更好
  • 最坏:O(n^2)
  • 平均:取决于增量序列的选择,通常为 O(n log^2 n) 或更好
  • 空间复杂度:O(1)
  • 稳定:否

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

(3)实现

//希尔排序
inline void shellSort(int* nums, int numsSize)
{
	int gap = 1;
	while (gap <= numsSize / 3) 
		gap = gap * 3 + 1; // 使用 Knuth 增量序列
		
	while (gap > 0)
	{
		for (int i = gap; i < numsSize; ++i)
		{
			int temp = nums[i];
			int j;
			for (j = i; j >= gap && nums[j - gap] > temp; j -= gap) 
				nums[j] = nums[j - gap];
			nums[j] = temp;
		}
		gap = (gap - 1) / 3; // 逆序列
	}
}

5.快速排序

快速排序的特点是非常快!!非常快,尤其是数据规模大的时候。
请添加图片描述
快速排序是一种分治算法,其基本思想是选择一个基准值(pivot),通过对数组进行分区操作,将数组分成两个子数组,其中左边的子数组中的元素小于等于基准值,右边的子数组中的元素大于基准值,然后递归地对子数组进行排序。这个过程不断重复,直到整个数组有序。

谨记:

  • 基准值尽量是中位数,可以随便选
  • 左右指针可以放数组两边,逐渐相互靠近
  • 交换左右指针所指元素来实现一边大一边小
  • 对产生的俩数组再进行快排

(3)复杂度分析

  • 最优时间复杂度:O(n log n)
  • 最差时间复杂度:O(n^2)
  • 平均时间复杂度:O(n log n)
  • 空间复杂度:O(log n) 到 O(n) - 取决于递归深度
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    可以看到千万级别的随机数据,耗时7秒,百万级甚至不足一秒

(3)实现

递归实现(数据量过大会爆栈)

inline void quickSort(int* nums, int numsSize)
{
	if (numsSize <= 1) return;

	//快排基准
	int pivot = nums[0];

	//左右索引分别位于数组两侧
	int left = 0;
	int right = numsSize - 1;

	//交替移动左右索引
	while (left < right)
	{
		//Right
		while (left < right)
		{
			if (nums[right] <= pivot)
			{
				swap(&nums[left], &nums[right]);
				break;
			}
			else right--;
		}
		//Left
		while (left < right)
		{

			if (nums[left] > pivot)
			{
				swap(&nums[left], &nums[right]);
				break;
			}
			else left++;
		}
	}

	//基准复位
	nums[left] = pivot;
	//递归
	//part1 (index): 0 - left
	quickSort(nums, left);
	//part2(index) : (left+1) - (numsSize-left-1)
	quickSort(&nums[left + 1], numsSize - 1 - left);
}

非递归实现

inline void quickSort(int* nums, int numsSize)
{
	if (numsSize <= 1) return;

	// 创建一个栈来模拟递归调用
	int* stack = (int*)malloc(numsSize * sizeof(int));
	if (stack == NULL) {
		// 错误处理,内存分配失败
		return;
	}

	int top = -1;
	stack[++top] = 0; // 入栈左边界
	stack[++top] = numsSize - 1; // 入栈右边界

	while (top >= 0) {
		// 出栈右边界和左边界
		int right = stack[top--];
		int left = stack[top--];

		// 划分区间
		int pivot = nums[left];
		int l = left, r = right;
		while (l < r) {
			while (l < r && nums[r] >= pivot) r--;
			if (l < r) nums[l++] = nums[r];

			while (l < r && nums[l] <= pivot) l++;
			if (l < r) nums[r--] = nums[l];
		}
		nums[l] = pivot;

		// 对左右子数组进行入栈排序
		if (left < l - 1) {
			stack[++top] = left;
			stack[++top] = l - 1;
		}
		if (right > l + 1) {
			stack[++top] = l + 1;
			stack[++top] = right;
		}
	}

	free(stack); // 释放动态分配的栈内存
}

今天写到这hh,其他的代码去年也写过了,只是文没写完,写一遍复习这文当就笔记了

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

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

相关文章

Flask(Jinja2) 服务端模板注入漏洞(SSTI)

Flask&#xff08;Jinja2&#xff09; 服务端模板注入漏洞(SSTI) 参考 https://www.freebuf.com/articles/web/260504.html 验证漏洞存在 ?name{{7*7}} 回显49说明漏洞存在 vulhub给出的payload: {% for c in [].__class__.__base__.__subclasses__() %} {% if c.__name__…

多测师肖sir_高级金牌讲师_jenkins搭建

jenkins操作手册 一、jenkins介绍 1、持续集成&#xff08;CI&#xff09; Continuous integration 持续集成 团队开发成员每天都有集成他们的工作&#xff0c;通过每个成员每天至少集成一次&#xff0c;也就意味着一天有可 能多次集成。在工作中我们引入持续集成&#xff0c;通…

ESP-IDF-V5.1.1使用websocket

IDF Component Registry (espressif.com) 在windows系统中&#xff0c;在项目目录下使用命令 idf.py add-dependency "espressif/esp_websocket_client^1.1.0"

OneNote Win10自带的宝藏笔记工具

大家在上学期间&#xff0c;通常要做大量的笔记&#xff0c;为后期巩固和复习。中学小学期间&#xff0c;大家往往是通过手写笔记来记录所学知识&#xff0c;然而上了大学&#xff0c;更加自由的学习条件下&#xff0c;大家逐渐开始用电子产品来做笔记。无论是平板还是电脑&…

【解刊】1区TOP,国人友好,仅1个月左右录用,2天见刊!

计算机类 • 好刊解读 今天小编带来Elsevier旗下计算机领域好刊的解读&#xff0c;如有相关领域作者有意向投稿&#xff0c;可作为重点关注&#xff01;后文有同领域快刊发表案例&#xff0c;供您投稿参考~ 01 期刊简介 Knowledge-Based Systems ☑️出版社&#xff1a;Els…

Visual Studio 2022 + OpenCV 4.5.2 安装与配置教程

目录 OpenCV的下载与配置Visual Studio 2022的配置新建工程新建文件新建项目属性表环境配置测试先写一个输出将OpenCV的动态链接库添加到项目的 x64 | Debug下测试配置效果 Other OpenCV的下载与配置 参考这个OpenCV的下载与环境变量的配置&#xff1a; Windows10CLionOpenCV4…

「掌握创意,释放想象」——Photoshop 2023,你的无限可能!

Adobe Photoshop 2023(PS2023) 来了,全世界数以百万计的设计师、摄影师和艺术家使用 Photoshop 将不可能变为可能。从海报到包装&#xff0c;从基本的横幅到漂亮的网站&#xff0c;从令人难忘的徽标到引人注目的图标&#xff0c;Photoshop 2023让创意世界不断前进。借助直观的工…

Amazon EC2 安全可调用的云虚拟主机服务器

&#x1f497;wei_shuo的个人主页 &#x1f4ab;wei_shuo的学习社区 &#x1f310;Hello World &#xff01; Amazon EC2 打造全新的科技链 Amazon Elastic Compute Cloud&#xff08;Amazon EC2&#xff09;提供最广泛、最深入的计算平台&#xff0c;拥有超过 500 个实例&…

开放式耳机能保护听力吗?开放式耳机有哪些优缺点?

先说答案&#xff0c;开放式耳机是可以保护听力的&#xff01; 想要了解开放式耳机是否能保护听力&#xff0c;就要先知道什么是开放式耳机&#xff0c;开放式耳机是一种无需入耳&#xff0c;并且使用时不会堵塞耳道&#xff0c;也不会隔绝外界声音的蓝牙耳机。 一、开放式耳…

Gitlab服务器配置LDAP指导

ssh登录gitlab服务器&#xff1a;192.168.1.203修改配置文件 sudo su vim /etc/gitlab/gitlab.rb找到ldap_enabled和ldap_servers关键字并修改参数 保存配置文件并重新载入配置 gitlab-ctl reconfigure检查ldap相关配置是否成功&#xff08;列出前100个用户&#xff0c;若没…

JDBC SQL Server Source Connector: 一览与实践

在快速发展的数据驱动业务环境中&#xff0c;确保数据在各个系统间高效、准确地同步至关重要。为了进一步的数据处理和分析&#xff0c;经常需要将这些数据同步到其他数据处理系统。Apache SeaTunnel 提供了一个强大而灵活的数据集成框架&#xff0c;使得从 SQL Server 到其他系…

学不会Handler?那是因为你还没有看过这篇文章

对Android开发者来suo&#xff0c;Handler机制无疑是最重要的知识之一&#xff0c;大家肯定也已经看过诸多有关Handler的教学文章了&#xff0c;为什么你会看到这篇文章&#xff1f;显然是你还没学会&#xff0c;或者忘记了&#xff0c;或者想深究一下。好消息是&#xff0c;这…

相对而言,嵌入式开发和纯软件开发哪个更有优势?

相对而言&#xff0c;嵌入式开发和纯软件开发哪个更有优势&#xff1f; 你关心什么方面的优势&#xff1f; 1. 钱途&#xff1f; 纯软件胜&#xff0c;纯软件天花板高很多。嵌入式开发只能说还行。不过天花板这东西是对牛人(至少前30%的人)而言的&#xff0c;混饭吃的话差别就…

JTS: 16 Orientation 方向

这里写目录标题 版本代码 版本 org.locationtech.jts:jts-core:1.19.0 链接: github 代码 public static void main(String[] args) {OrientationUse orientationUse new OrientationUse();orientationUse.test02();}public void test02() {A new Coordinate(2, 1);B new …

高校为什么需要大数据挖掘平台?

目前数据挖掘已经成为各种应用领域的重要技术&#xff0c;大学数据挖掘课程的开放已经出现。数据挖掘课程整合了多门学科知识。该课程包括各种理论知识&#xff0c;也离不开相关的实用技术。整个教学过程是培养和提高学生全面创新和解决问题的能力。过去&#xff0c;教学过程理…

IDEA插件分享,支持接口调试!

平时我们在写完接口需要填入postman、Apipost等工具进行接口调试&#xff0c;今天给大家推荐一款IDEA插件Apipost-helper&#xff0c;写完代码直接可以进行调试&#xff0c;而且支持生成接口文档&#xff0c;JAVA工程师必用&#xff01; 可以点击下方链接或在插件商店中搜索安…

netty基本用法, 拆包、粘包等常见解决方案,看本文即可,不做原理说明,只进行实战操作

netty的基本用法 完整的介绍了netty最基本的发送byte、string、byteBuf发送接收数据&#xff0c;以及拆包、粘包演示&#xff0c;拆包、粘包的解决方案。看netty的用法只看本篇足以&#xff0c;本篇只说用法&#xff0c;不讲底层原理。 详细demo的git地址 示例的通用代码 客…

KT148A语音芯片的下载板子导入F1A声音下载操作多次只成功一次都没有声音

一、问题简介 为什么我使用KT148A语音芯片的下载板子&#xff0c;导入声音下载&#xff0c;操作好多次&#xff0c;只成功了一次&#xff0c;后面始终都没有声音 芯片分为两个版本&#xff0c;分别是按键版本和一线串口版本。看一下样品卡的校验码&#xff1a; 详细描述 1、如…

数学建模比赛中常用的建模提示词(数模prompt)

以下为数学建模比赛中常用的建模提示词&#xff0c;希望对你有所帮助&#xff01; 帮我总结一下数学建模有哪些预测类算法&#xff1f; 灰色预测模型级比检验是什么意思? 描述一下BP神经网络算法的建模步骤 对于分类变量与分类变量相关性分析用什么算法 前10年的数据分别是1&a…

京东店铺所有商品数据接口(JD.item_search_shop)

京东店铺所有商品数据接口是一种允许开发者在其应用程序中调用京东店铺所有商品数据的API接口。利用这一接口&#xff0c;开发者可以获取京东店铺的所有商品信息&#xff0c;包括商品标题、SKU信息、价格、优惠价、收藏数、销量、SKU图、标题、详情页图片等。 通过京东店铺所有…