[数据结构]———交换排序

news2024/11/15 12:49:09

目录

​编辑

​编辑 

1.交换排序

第一个定义了一个名为Swap的函数

 第二个三数取中

2.冒泡排序

代码解析

冒泡排序的特性总结:

3.快速排序

1. hoare版本

2. 挖坑法 

 代码解析

 3. 前后指针版本

 代码解析


1.交换排序


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

首先我们先介绍并创建两个函数,后面要用

第一个定义了一个名为Swap的函数

实现了交换两个整数指针所指向的值

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

 第二个三数取中

定义了一个名为GetMidi的函数用于确定三个位置beginmidiend在数组a中的中间值索引,确定并返回中间值的索引

int GetMidi(int* a, int begin, int end)
{
	int midi = (begin + end) / 2;
	// begin midi end 三个数选中位数
	if (a[begin] < a[midi])
	{
		if (a[midi] < a[end])
			return midi;
		else if (a[begin] > a[end])
			return begin;
		else
			return end;
	}
	else // a[begin] > a[midi]
	{
		if (a[midi] > a[end])
			return midi;
		else if (a[begin] < a[end])
			return begin;
		else
			return end;
	}
}


2.冒泡排序

代码解析

void BubbleSort(int* a, int n)//冒泡排序
{
	for (int j = 0; j < n; j++)
	{
		bool exchange = false;
		for (int i = 1; i < n - j; i++)
		{
			if (a[i - 1] > a[i])
			{
				Swap(&a[i - 1], &a[i]);
				exchange = true;
			}
		}

		if (exchange == false)
			break;
	}
}

冒泡排序的特性总结:


1. 冒泡排序是一种非常容易理解的排序
2. 时间复杂度:O(N^2)
3. 空间复杂度:O(1)
4. 稳定性:稳定

3.快速排序


快速排序是Hoare于1962年提出的一种二叉树结构的交换排序方法,

其基本思想为:任取待排序元素序列中的某元素作为基准值,按照该排序码将待排序集合分割成两子序列,左子序列中所有元素均小于基准值,右子序列中所有元素均大于基准值,然后最左右子序列重复该过程,直到所有元素都排列在相应位置上为止。 

// 假设按照升序对array数组中[left, right)区间中的元素进行排序
void QuickSort(int array[], int left, int right)
{
if(right - left <= 1)
return;
// 按照基准值对array数组的 [left, right)区间中的元素进行划分
int div = partion(array, left, right);
// 划分成功后以div为边界形成了左右两部分 [left, div) 和 [div+1, right)
// 递归排[left, div)
QuickSort(array, left, div);
// 递归排[div+1, right)
QuickSort(array, div+1, right);
}

上述为快速排序递归实现的主框架,发现与二叉树前序遍历规则非常像,同学们在写递归框架时可想想二叉树前序遍历规则即可快速写出来,后序只需分析如何按照基准值来对区间中数据进行划分的方式即可。
将区间按照基准值划分为左右两半部分的常见方式有:


1. hoare版本

在快速排序算法中,需要在找到左边比关键值大的元素和右边比关键值小的元素之后才进行元素交换,以确保左边的元素都比关键值小,右边的元素都比关键值大。但是在代码中目前的交换步骤存在问题,因为在while循环结束之后直接进行了一次元素交换,而应该是在找到左右指针位置后再进行交换。

int QuickSort1(int* a, int begin, int end)
{
	int midi = GetMidi(a, begin, end);
	Swap(&a[midi], &a[begin]);

	int left = begin, right = end;
	int keyi = begin;

	while (left < right)
	{
		// 右边找小
		while (left < right && a[right] >= a[keyi])
		{
			--right;
		}

		// 左边找大
		while (left < right && a[left] <= a[keyi])
		{
			++left;
		}

		Swap(&a[left], &a[right]);
	}

	Swap(&a[left], &a[keyi]);

	return left;
}

2. 挖坑法 

 代码解析

  1. 挖坑法
    • 使用挖坑法的思想,即每次在处理完左右指针位置的元素后,将最初选择的“坑”填入正确的位置。
  2. 函数逻辑
    • 首先在数组中选择基准值(pivot)并与起始位置的元素交换,这里选择的基准值为a[begin]
    • 使用两个指针beginend分别指向数组的起始和末尾,开始移动指针以找到需要交换的元素。
    • begin小于end时,进行以下操作:
      • 从右侧开始,找到第一个比基准值小的元素,将其填入“坑”中,同时更新“坑”的位置和end指针的位置。
      • 从左侧开始,找到第一个比基准值大的元素,将其填入之前右侧留下的“坑”中,同时更新“坑”的位置和begin指针的位置。
    • 最后,将基准值填入最后的“坑”中,返回该“坑”的位置,用于分割左右子数组。
  3. 返回值
    • 函数返回的是基准值在排序后的位置,用于在递归调用中分割左右子数组。
//2.挖坑法
int QuickSort2(int* a, int begin, int end)
{
	int midi = GetMidi(a, begin, end);
	Swap(&a[midi], &a[begin]);

	int key = a[begin];
	int hole = begin;
	while (begin < end)
	{
		// 右边找小,填到左边的坑
		while (begin < end && a[end] >= key)
		{
			--end;
		}

		a[hole] = a[end];
		hole = end;

		// 左边找大,填到右边的坑
		while (begin < end && a[begin] <= key)
		{
			++begin;
		}

		a[hole] = a[begin];
		hole = begin;
	}

	a[hole] = key;
	return hole;
}

 

 3. 前后指针版本

 代码解析

将数组分成两个子数组,左边的子数组中的元素都小于等于中间元素,右边的子数组中的元素都大于等于中间元素,并返回中间元素的索引

int QuickSort3(int* a, int begin, int end)
{
	int midi = GetMidi(a, begin, end);
	Swap(&a[midi], &a[begin]);
	int keyi = begin;

	int prev = begin;
	int cur = prev + 1;
	while (cur <= end)
	{
		if (a[cur] < a[keyi] && ++prev != cur)
			Swap(&a[prev], &a[cur]);

		++cur;
	}

	Swap(&a[prev], &a[keyi]);
	keyi = prev;
	return keyi;
}

 

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

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

相关文章

maven插件:dockerfile-maven-plugin和docker-maven-plugin

Maven插件dockerfile-maven-plugin和docker-maven-plugin都是为Java开发人员提供了一种便捷的方式&#xff0c;通过Maven构建流程来自动化创建、管理和推送Docker镜像。虽然它们有着相似的目标&#xff0c;即集成Docker与Maven项目&#xff0c;但这两个插件在实现细节、功能侧重…

windows驱动开发-WDF对象

WDF封装了大量的WDF对象&#xff0c;不过&#xff0c;和应用层不一样&#xff0c;不用去尝试从WDF框架对象类上派生和改写原有的WDF类&#xff0c;本意WDF就是希望我们使用这些对象和类&#xff0c;而不是创造新的奇怪的类。 每个WDF对象都代表着对一项驱动需要使用的子功能的…

骑缝电子章怎么盖?

盖骑缝电子章通常涉及几个基本步骤&#xff0c;这里提供一个通用的流程&#xff0c;适用于大多数电子文档处理软件&#xff0c;尤其是那些支持电子签名和印章功能的软件&#xff0c;比如Adobe Acrobat Pro DC、e-章宝(易友EU3000智能盖章软件)等。请注意&#xff0c;具体操作可…

附录3-小程序常用事件

目录 1 点击事件 tap 2 文本框输入事件 input 3 状态改变事件 change 4 下拉刷新事件 onPullDownRefresh() 5 上拉触底事件 onReachBottom() 1 点击事件 tap 2 文本框输入事件 input 可以使用 e.detail.value 打印出当前文本框的值 我现在在文本框中依次输入12345&…

C语言 | Leetcode C语言题解之第62题不同路径

题目&#xff1a; 题解&#xff1a; int uniquePaths(int m, int n) {long long ans 1;for (int x n, y 1; y < m; x, y) {ans ans * x / y;}return ans; }

【linuxC语言】exec函数族

文章目录 前言一、exec函数族二、示例代码2.1 代码12.2 代码22.3 代码3 总结 前言 在Linux环境下&#xff0c;C语言提供了一组强大的函数族&#xff0c;即exec函数族&#xff0c;用于执行其他程序。这些函数允许程序在运行时加载并执行不同的程序&#xff0c;从而实现了程序之…

spring boot 自定义starter示例

springboot 约定规范 Starter项目的命名规范 建议自定义的starter 以 xxx-spring-boot-starter 命名&#xff0c;官方的Starter一般都是以spring-boot-starter-为前缀。这样做的目的是为了避免与官方或其他第三方提供的Starter产生冲突或混淆。 Starter项目的结构规范(重要) …

详解SDRAM基本原理以及FPGA实现读写控制

文章目录 一、SDRAM简介二、SDRAM存取结构以及原理2.1 BANK以及存储单元结构2.2 功能框图2.3 SDRAM速度等级以及容量计算 三、SDRAM操作命令3.1 禁止命令&#xff1a; 4b1xxx3.2 空操作命令&#xff1a;4b01113.3 激活命令&#xff1a;4b00113.4 读命令&#xff1a;4b01013.5 写…

spring的常用注解

&#x1f4dd;个人主页&#xff1a;五敷有你 &#x1f525;系列专栏&#xff1a;Spring⛺️稳中求进&#xff0c;晒太阳 Spring框架注解&#xff1a; 给容器中注入组件 &#xff08;1&#xff09;包扫描组件标注注解 Component&#xff1a; 用于标识一个类作为组件&am…

【数据结构(十)】Map和Set

❣博主主页: 33的博客❣ ▶️文章专栏分类:数据结构◀️ &#x1f69a;我的代码仓库: 33的代码仓库&#x1f69a; &#x1faf5;&#x1faf5;&#x1faf5;关注我带你学更多数据结构知识 目录 1.前言2.搜索树2.1 概念2.2实现二叉搜索树 2.4性能分析3.搜索3.Map3.1Map说明3.2 M…

【UnityRPG游戏制作】Unity_RPG项目之场景环境搭建和解析

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 秩沅 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a;Uni…

图论之最短路算法模板总结

来个大致的分类&#xff1a; 朴素的迪杰斯特拉&#xff1a; 实现&#xff1a; 我们让s表示当前已经确定的最短距离的点&#xff0c;我们找到一个不在s中的距离最近的点t&#xff0c;并用t来更新其他的点。 下面是AC代码&#xff1a; #include<bits/stdc.h> using nam…

C++之const用法小结

在C中&#xff0c;const关键字具有多种用法&#xff0c;主要用于声明常量&#xff0c;确保某些变量的值在程序运行期间不会被修改。以下是const在C中的一些常见用法&#xff1a; 1.声明常量&#xff1a; 使用const声明的变量是常量&#xff0c;其值在初始化后不能再被修改。 …

关于海康相机和镜头参数的记录

对比MV-CS020-10UC和大家用的最多的MV-CS016-10UC 其实前者适合雷达站使用&#xff0c;后者适合自瞄使用 一&#xff1a;MV-CS020-10UC的参数 二&#xff1a;对比 三&#xff1a;海康镜头选型工具

mysql从入门到起飞+面试基础题

mysql基础 MySQL基础 企业面试题1 代码 select m.id,m.num from ( select t.id as id,count(1) num from ( select ra.requester_id as id from RequestAccepted raunion all select ra.accepter_id as id from RequestAccepted ra ) t group by t.id ) m group by id ord…

C++学习第十八课:STL中的`string`类深度解析

C学习第十八课&#xff1a;STL中的string类深度解析 在C标准模板库&#xff08;STL&#xff09;中&#xff0c;std::string是一个提供了大量功能和操作的类&#xff0c;用于处理和存储字符串数据。std::string不仅包含了传统的C风格字符串&#xff08;如char*&#xff09;所提…

算法二:DOM - 将DOM节点元素转换成JSON字符串

题目&#xff1a; 将DOM节点元素转换成JSON的格式 例如 <div class"root"><div class"child1"><p></p></div><span></span><div><div><p></p></div></div><p></…

XY_RE复现(六)

馒头 考数据结构的好像 有一个建树的函数 __int64 __fastcall initHuffmanTree(void **a1) {__int64 v1; // rcx__int64 v2; // rdxchar v4; // [rsp27h] [rbp-9h]int j; // [rsp28h] [rbp-8h]int i; // [rsp2Ch] [rbp-4h]*a1 malloc(0x3C0ui64);for ( i 1; i < 47; i )…

OpenGL 入门(一)—— OpenGL 基础

1、OpenGL 基础知识 1.1 OpenGL 简介 OpenGL&#xff08;Open Graphics Library&#xff09;是图形领域的工业标准&#xff0c;是一套跨编程语言、跨平台、专业的图形编程&#xff08;软件&#xff09;接口。它用于二维、三维图像&#xff0c;是一个功能强大&#xff0c;调用…

一个C++小程序调试过程记录

Top 20 C Projects With Source Code [2024 Update]https://www.interviewbit.com/blog/cpp-projects/ 这个网页有一些简单的C程序的源码&#xff0c;闲来无事&#xff0c;把第一个程序&#xff08;Bookshop Management System Using C&#xff09;的源码下载了下来。 源文件…