快速排序与归并排序(非递归)

目录

快速排序(双指针法)

原理

代码

快速排序(非递归)

原理

代码

归并排序

介绍

优点

缺点

图片

原理

代码

归并排序(非递归)

代码


快速排序(双指针法)

快速排序的精髓在于将数组根据关键值分成左右两块,由此衍生出霍尔快排,挖坑法等一系列方法,在这里我们要介绍一下双指针法

原理

第一个指针pre指向开头,第二个指针cur指向第二个元素

cur持续向前查找,找到某个位置小于关键值时,将cur指向的值与pre的下一个值进行交换(没错,是下一个,这样就可以将第一个位置的关键值保存下来)

交换还有个限制条件就是pre的下一个位置不能是cur

交换完成后cur与pre指向下一个位置

循环退出条件为cur超出数组范围

退出循环后,将pre位置的值与关键值进行交换(因为pre位置始终小于关键值)

最后和普通的递归一样递归执行左右两侧即可

代码

void quicksort(int* arr, int left, int right) {//双指针
	if (left >= right)
		return;
	int cur = left + 1, pre = left;
	while (cur <= right) {
		if (arr[cur] < arr[left] && ++pre < cur)
			swap(&arr[cur], &arr[pre]);
		cur++;
	}
	swap(&arr[left], &arr[pre]);
	quicksort(arr, left, pre - 1);
	quicksort(arr, pre + 1, right);
}

快速排序(非递归)

原理

我们可以使用栈进行模拟递归,首先创建一个栈,将数组的左右边界打入栈中,进入循环

当栈不为空时持续执行循环

根据自己的实际情况判断左右边界,如果先打入的是右边界,那么栈顶元素就是左边界

取出左右边界后,执行一次快排并返回关键值所在位置

如果关键值左侧不止一个元素,那么就打入左侧的左右边界

右侧同理

这样,我们就实现了非递归的快速排序

代码

int part(int* arr, int left, int right) {
	if (left >= right)
		return 0;
	int cur = left + 1, pre = left;
	while (cur <= right) {
		if (arr[cur] < arr[left] && ++pre < cur)
			swap(&arr[cur], &arr[pre]);
		cur++;
	}
	swap(&arr[left], &arr[pre]);
	return arr[pre];
}
void quicksort1(int* arr, int left, int right) {//非递归
	Stack stack;
	StackInit(&stack);
	StackPush(&stack, right);
	StackPush(&stack, left);
	while (!StackEmpty(&stack)) {
		int begin = StackTop(&stack);
		StackPop(&stack);
		int end = StackTop(&stack);
		StackPop(&stack);
		int key = part(arr, begin, end);
		if (key - 1 > begin) {
			StackPush(&stack, key-1);
			StackPush(&stack, begin);
		}
		if (key + 1 < end) {
			StackPush(&stack, end);
			StackPush(&stack, key + 1);
		}
	}
}

归并排序

介绍

归并排序是通过不断细分左右边界,使局部有序后扩大范围使整体有序的排序

优点

效率较高,且不会受原数组排列顺序影响

缺点

需要额外开辟一块等大的数组

图片

原理

创建等大的辅助数组

拆分为两块数组

先递归自身使左右两边有序

与链表类似

比较分成的两块有序数组的元素大小并排列在辅助数组中

整体有序后拷贝到原数组中

代码

void _Mergesort(int* arr, int*tmp,int left,int right) {
	if (left >= right)
		return;
	int mid = (left + right) / 2;
	int begin1 = left, end1 = mid, begin2 = mid + 1, end2 = right,i=left;
	_Mergesort(arr, tmp, begin1, end1);
	_Mergesort(arr, tmp, begin2, end2);
	while (begin1 <= end1 && begin2 <= end2) {
		if (arr[begin1] < arr[begin2]) {
			tmp[i++] = arr[begin1];
			begin1++;
		}
		else {
			tmp[i++] = arr[begin2];
			begin2++;
		}
	}
	while (begin1 <= end1) {
		tmp[i++] = arr[begin1];
		begin1++;
	}
	while (begin2 <= end2) {
		tmp[i++] = arr[begin2];
		begin2++;
	}
	memcpy(arr + left, tmp + left, sizeof(int) * (right - left + 1));
}

归并排序(非递归)

我们要用到希尔排序时创建的一个变量:gap

gap为一个数组拆分后单个小数组的元素个数

最小为一

当gap小于总数时

按照gap为一组,两组为一大组的顺序从左到右进行排序

当右侧起始位置超出时,直接退出,因为左侧小数组本身就是有序的

右侧终止位置超出时修正即可

单次遍历结束后将辅助数组元素拷贝回原数组即可

代码

void MergesortNonR(int* arr, int n) {
	int gap = 1;//gap为每小组元素个数,两个小组为一大组进行比较
	int* tmp = (int*)malloc(sizeof(int) * n),i;
	while (gap < n) {
		for (i = 0; i < n; i+=2*gap) {
			int begin1 = i, end1 = begin1 + gap - 1;
			int begin2 = end1 + 1, end2 = begin2 + gap - 1, j = i;
			if (begin2 >= n)
				break;
			if (end2 >= n)
				end2 = n - 1;
			while (begin1 <= end1 && begin2 <= end2) {
				if (arr[begin1] > arr[begin2])
					tmp[j++] = arr[begin2++];
				else
					tmp[j++] = arr[begin1++];
			}
			while (begin1 <= end1)
				tmp[j++] = arr[begin1++];
			while (begin2 <= end2)
				tmp[j++] = arr[begin2++];
			memcpy(arr + i, tmp + i, sizeof(int) * gap * 2);
		}
		gap *= 2;
	}
	free(tmp);
	tmp = NULL;
}

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

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

相关文章

【讲解下常见的分类算法,什么是分类算法?】

&#x1f3a5;博主&#xff1a;程序员不想YY啊 &#x1f4ab;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f917;点赞&#x1f388;收藏⭐再看&#x1f4ab;养成习惯 ✨希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出…

redis如何实现分布式锁

Redisson是怎么实现分布式锁的 分布式锁&#xff1a;Redisson 提供了一种简单而强大的方式来实现分布式锁。 它支持多种锁模式&#xff0c;如公平锁、可重入锁、读写锁等&#xff0c;并且提供了锁的超时设置和自动释放功能。 锁的获取 在Redisson中常见获取锁的方式有 lock() …

面向对象概述

自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 面向对象&#xff08;Object Oriented&#xff09;的英文缩写是OO&#xff0c;它是一种设计思想。从20世纪60年代提出面向对象的概念到现在&#xff…

Cyber Weekly #9

赛博新闻 1、OpenAI&#xff1a;GPTs向全部用户开放&#xff0c;使用GPT-4o OpenAI宣布所有ChatGPT免费用户现在可以在GPT商店中使用GPTs&#xff0c;并且这些GPTs现在使用最新的GPT-4o模型。 2、马斯克 vs. Yann LeCun 这一周&#xff0c;AI圈最热闹的莫过于马斯克和LeCun的…

scGPT实验解读

本篇内容为发表在Nature Methods上的scGPT的部分实验内容 来自&#xff1a;scGPT: toward building a foundation model for single-cell multi-omics using generative AI, Nature Methods, 2024 目录 scGPT揭示特定细胞状态的基因网络缩放法则和迁移学习中的上下文效应 scGP…

基于安卓的虫害识别软件设计--(2)模型性能可视化|混淆矩阵、热力图

1.混淆矩阵&#xff08;Confusion Matrix&#xff09; 1.1基础理论 &#xff08;1&#xff09;在机器学习、深度学习领域中&#xff0c;混淆矩阵常用于监督学习&#xff0c;匹配矩阵常用于无监督学习。主要用来比较分类结果和实际预测值。 &#xff08;2&#xff09;图中表达…

物理模拟技术在AI绘画中的革新作用

引言&#xff1a; 随着人工智能&#xff08;AI&#xff09;技术的飞速发展&#xff0c;艺术领域也迎来了一场创新的革命。AI绘画&#xff0c;作为这场革命的重要组成部分&#xff0c;不仅改变了传统艺术创作的模式&#xff0c;而且为艺术家提供了前所未有的创作工具。在这一过程…

Linux基础1-基本指令1

1.Linux学习前言 Linux的学习非常重要&#xff0c;我们学习Linux的第一步是在电脑中搭建Linux环境。 对于没有搭建过的可以看这阿伟t的一篇文章 【Linux入门】Linux环境配置-CSDN博客 我的环境为XShell,运行的云服务器是阿里云 2.本章重点 1.显示当前目录下的所有文件…

软件杯 题目:基于卷积神经网络的手写字符识别 - 深度学习

文章目录 0 前言1 简介2 LeNet-5 模型的介绍2.1 结构解析2.2 C1层2.3 S2层S2层和C3层连接 2.4 F6与C5层 3 写数字识别算法模型的构建3.1 输入层设计3.2 激活函数的选取3.3 卷积层设计3.4 降采样层3.5 输出层设计 4 网络模型的总体结构5 部分实现代码6 在线手写识别7 最后 0 前言…

展现市场布局雄心,ATFX再度亮相非洲峰会,开启区域市场新篇章

自2023年全球市场营销战略部署实施以来&#xff0c;ATFX在全球各区域市场取得了丰硕成果&#xff0c;其品牌实力、知名度、影响力均有大幅提升。在这场全球扩张的征程中&#xff0c;非洲市场日益成为集团关注的焦点。自2023年首次踏上这片充满潜力的市场以来&#xff0c;ATFX持…

定义类并创建类的实例

自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 在Python中&#xff0c;类表示具有相同属性和方法的对象的集合。在使用类时&#xff0c;需要先定义类&#xff0c;然后再创建类的实例&#xff0c;通…

谨以此文章记录我的蓝桥杯备赛过程

以国优秀结束了蓝桥杯cb组 鄙人来自电信学院&#xff0c;非科班出身&#xff0c;在寒假&#xff0c;大约2024年2月份&#xff0c;跟着黑马程序员将c基础语法学完了&#xff0c;因为过年&#xff0c;事情较多&#xff0c;没在学了。 最初就是抱着拿省三的态度去打这个比赛的&a…

低代码是什么?开发系统更有什么优势?

低代码&#xff08;Low-Code&#xff09;是一种应用开发方法&#xff0c;它采用图形化界面和预构建的模块&#xff0c;使得开发者能够通过少量的手动编程来快速创建应用程序。这种方法显著减少了传统软件开发中的手动编码量&#xff0c;提高了开发效率&#xff0c;降低了技术门…

图形学初识--多边形剪裁算法

文章目录 前言正文为什么需要多边形剪裁算法&#xff1f;前置知识二维直线直线方程&#xff1a;距离本质&#xff1a;点和直线距离关系&#xff1a; 三维平面平面方程距离本质&#xff1a;点和直线距离关系&#xff1a; Suntherland hodgman算法基本介绍基本思想二维举例问题描…

mysql中EXPLAIN详解

大家好。众所周知&#xff0c;MySQL 查询优化器的各种基于成本和规则的优化会后生成一个所谓的执行计划&#xff0c;这个执行计划展示了接下来具体执行查询的方式。在日常工作过程中&#xff0c;我们可以使用EXPLAIN语句来查看某个查询语句的具体执行计划&#xff0c; 今天我们…

椭圆轨道的周期性运动轨道

一、背景介绍 本节将从轨道六根数的角度&#xff0c;探究目标星为椭圆轨道&#xff0c;追踪星周期性环绕目标的必要条件。根据航天动力学的原理&#xff0c;对于一个椭圆轨道&#xff0c;其轨道能量为 对于能够不产生漂移的情况&#xff0c;绕飞编队的能量。对于追踪星到目标星…

(2024,扩散,去噪调度,维度,误差,收敛速度)适应基于分数的扩散模型中的未知低维结构

Adapting to Unknown Low-Dimensional Structures in Score-Based Diffusion Models 公和众和号&#xff1a;EDPJ&#xff08;进 Q 交流群&#xff1a;922230617 或加 VX&#xff1a;CV_EDPJ 进 V 交流群&#xff09; 目录 0. 摘要 1. 引言 1.1 扩散模型 1.2 现有结果的不…

Xilinx RFSOC 47DR 8收8发 信号处理板卡

系统资源如图所示&#xff1a;  FPGA采用XCZU47DR 1156芯片&#xff0c;PS端搭载一组64Bit DDR4,容量为4GB,最高支持速率&#xff1a;2400MT/s;  PS端挂载两片QSPI X4 FLASH&#xff1b;  PS支持一路NVME存储&#xff1b;  PS端挂载SD接口&#xff0c;用于存储程序&…

图解大模型分布式并行各种通信原语

背景 在分布式集群上执行大模型任务时候&#xff0c;往往使用到数据并行&#xff0c;流水线并行&#xff0c;张量并行等技术&#xff0c;这些技术本质上也就是对数据进行各种方案的切分&#xff0c;然后放到不同的节点上运算。不同节点在计算的过程中需要对数据分发或者同步等…

LeetCode刷题之HOT100之在排序数组中查找元素的第一个和最后一个位置

下午雨变小了&#xff0c;但我并未去实验室&#xff0c;难得的一天呆在宿舍。有些无聊&#xff0c;看看这个&#xff0c;弄弄那个&#xff0c;听听歌&#xff0c;消磨时间。不知觉中时间指针蹦到了九点&#xff0c;做题啦&#xff01;朋友推荐了 Eason 的 2010-DUO 演唱会&…