归并排序与逆序对问题(C语言版)
一、引言
归并排序是一种高效且稳定的排序方法,而逆序对问题是算法领域的一个经典问题,本文教大家如何实现归并排序,以及如何使用归并排序去结果逆序对问题
二、归并排序
归并排序思想
分解:将待排序的数组分成两半,递归地对这两半进行归并排序,直到每个子数组的大小为1(此时已经是有序的)。
合并:将两个已排序的子数组合并成一个新的有序数组。合并过程通常使用两个指针,分别指向两个子数组的当前元素,比较这两个元素并将较小的元素放入结果数组中,直到所有元素都被合并。
我们借助递归可以很好的实现数据的分解和合并,我们可以借助代码区理解归并排序
#include <stdio.h>#define MAXSIZE 100int merge[MAXSIZE]; void Merge(int a[], int left, int right, int middle) {int i = left; int j = middle + 1; int k = left; while (i <= middle && j <= right) {if (a[i] <= a[j]) {merge[k++] = a[i++]; }else {merge[k++] = a[j++];}}while (i <= middle) {merge[k++] = a[i++];}while (j <= right) {merge[k++] = a[j++];}for (i = left; i <= right; i++) {a[i] = merge[i];}
}void Mergesort(int a[], int left, int right) {if (left < right) {int middle = (left + right) / 2;Mergesort(a, left, middle); Mergesort(a, middle + 1, right); Merge(a, left, right, middle); }
}void show(int a[], int n) {for (int i = 0; i < n; i++) {printf("%d ", a[i]);}printf("\n");
}int main() {int a[MAXSIZE];int n;printf("请输入待排关键字个数(n>0): ");scanf_s("%d", &n);printf("请依次输入关键字的数据值:\n");for (int i = 0; i < n; i++) {scanf_s("%d", &a[i]);}Mergesort(a, 0, n - 1); printf("该组数据排序后的结果: ");show(a, n);printf("该组数据逆序对的个数: %d\n", count); printf("========================================================================================================================");return 0;
}
这段代码便是归并排序的核心代码,其中分解通过递归的方式进行,而合并,我们则定义了一个函数
void Merge(int a[], int left, int right, int middle) {int i = left; int j = middle + 1; int k = left; while (i <= middle && j <= right) {if (a[i] <= a[j]) {merge[k++] = a[i++]; }else {merge[k++] = a[j++];count += (middle - i + 1); }}while (i <= middle) {merge[k++] = a[i++];}while (j <= right) {merge[k++] = a[j++];}for (i = left; i <= right; i++) {a[i] = merge[i];}
}
该函数我们可以实现两个有序函数的合并,合并之后还是有序函数
那么我们如何保证我们要合并的两个数组原本是有序的呢?这就需要我们探究一下递归的本质了
我们通过如下递归,最后会将数组分解为一个一个的单独的数字
void Mergesort(int a[], int left, int right) {if (left < right) {int middle = (left + right) / 2;Mergesort(a, left, middle); Mergesort(a, middle + 1, right); Merge(a, left, right, middle); }
}
这些一个一个的数字就是我们最早的有序数组,之后我们通过有序数组产生的数组,也都是有序的,经过我们的拆分和合并,最后就会产生一个合并好的最终的有序数组
这样归并排序的全过程就结束了
三、逆序对
1.何为逆序对
逆序对是指在一个序列中,两个元素的相对位置与它们的大小关系不一致。具体来说,对于一个序列中的两个元素 a[i]a[i] 和 a[j]a[j],如果 i<j i<j 且 a[i]>a[j] a[i]>a[j],那么就称这个对 (a[i],a[j])(a[i],a[j]) 为一个逆序对。
例如,在序列 [3,1,2][3,1,2] 中:
- 逆序对有 (3,1)(3,1) 和 (3,2)(3,2),因为 33 在 11 和 22 之前,但 33 的值大于它们。
- 而 (1,2)(1,2) 不是逆序对,因为 1<21<2。
逆序对的数量在计算排序算法的复杂度、分析数组的有序性等方面有重要应用。在某些排序算法中,逆序对的数量可以用来衡量数组的“无序程度”。
简而言之,就是前面的数比后面的数大,那么这两个数的下标就构成了逆序对
2.如何用归并思想求取逆序对
代码如下
#include <stdio.h>#define MAXSIZE 100int count = 0;
int merge[MAXSIZE]; void Merge(int a[], int left, int right, int middle) {int i = left; int j = middle + 1; int k = left; while (i <= middle && j <= right) {if (a[i] <= a[j]) {merge[k++] = a[i++]; }else {merge[k++] = a[j++];count += (middle - i + 1); }}while (i <= middle) {merge[k++] = a[i++];}while (j <= right) {merge[k++] = a[j++];}for (i = left; i <= right; i++) {a[i] = merge[i];}
}void Mergesort(int a[], int left, int right) {if (left < right) {int middle = (left + right) / 2;Mergesort(a, left, middle); Mergesort(a, middle + 1, right); Merge(a, left, right, middle); }
}void show(int a[], int n) {for (int i = 0; i < n; i++) {printf("%d ", a[i]);}printf("\n");
}int main() {int a[MAXSIZE];int n;printf("请输入待排关键字个数(n>0): ");scanf_s("%d", &n);printf("请依次输入关键字的数据值:\n");for (int i = 0; i < n; i++) {scanf_s("%d", &a[i]);}Mergesort(a, 0, n - 1); printf("该组数据排序后的结果: ");show(a, n);printf("该组数据逆序对的个数: %d\n", count); printf("========================================================================================================================");return 0;
}
其实逆序对的求取,我们只需要在我们归并排序的基础上加入几行代码便可,其中最核心的是下面的一段
int i = left; int j = middle + 1; int k = left; while (i <= middle && j <= right) {if (a[i] <= a[j]) {merge[k++] = a[i++]; }else {merge[k++] = a[j++];count += (middle - i + 1); }}
当我们的右边数组要比左边数组的数小时,便构成了逆序对的条件,但是这样的依次移动会产生几个逆序对呢,我们可以推断一下
我们左边的数列是有序的,当右边的某个数比左边的小时,它比左边那个数组中的右边的数都要小
所以
count += (middle - i + 1);
最后的逆序对的个数便是count的值
四、结语
今天微服务的学习要放在晚上了
相关文章:
归并排序与逆序对问题(C语言版)
一、引言 归并排序是一种高效且稳定的排序方法,而逆序对问题是算法领域的一个经典问题,本文教大家如何实现归并排序,以及如何使用归并排序去结果逆序对问题 二、归并排序 归并排序思想 分解:将待排序的数组分成两半,…...

网络爬虫总结与未来方向
通过深入学习和实际操作,网络爬虫技术从基础到进阶得以系统掌握。本节将全面总结关键内容,并结合前沿技术趋势与最新资料,为开发者提供实用性强的深度思考和方案建议。 1. 网络爬虫技术发展趋势 1.1 趋势一:高性能分布式爬虫 随…...

C++ 核心数据结构:Stack 与 Queue 类深度解析
🌟快来参与讨论💬,点赞👍、收藏⭐、分享📤,共创活力社区。 🌟 目录 💯前言 💯Stack 类 (一)Stack 类的概念与特点 (二&#x…...
Python枚举类详解:用enum模块高效管理常量数据
《Python OpenCV从菜鸟到高手》带你进入图像处理与计算机视觉的大门! 在编程中,常量的管理是一个关键环节,合理的管理常量可以提高代码的可读性和可维护性。Python的enum模块提供了一种有效的方式来组织常量数据,通过枚举类(Enum)将相关的常量值集合在一起,使代码更具结…...

企业OA管理系统:Spring Boot技术深度探索
4系统概要设计 4.1概述 本系统采用B/S结构(Browser/Server,浏览器/服务器结构)和基于Web服务两种模式,是一个适用于Internet环境下的模型结构。只要用户能连上Internet,便可以在任何时间、任何地点使用。系统工作原理图如图4-1所示: 图4-1系统工作原理…...

汽车免拆诊断案例 | 2012款路虎揽胜运动版柴油车加速无力
故障现象 一辆2012款路虎揽胜运动版车,搭载3.0T柴油发动机(型号为306DT),累计行驶里程约为10.2万km。车主进厂反映,车辆行驶中加速无力,且发动机故障灯异常点亮。 故障诊断 接车后试车,发动…...

uniapp接入高德地图
下面代码兼容安卓APP和H5 高德地图官网:我的应用 | 高德控制台 ,绑定服务选择《Web端(JS API)》 /utils/map.js 需要设置你自己的key和安全密钥 export function myAMap() {return new Promise(function(resolve, reject) {if (typeof window.onLoadM…...

(UI自动化测试)web自动化测试
web自动化测试 UI自动化测试介绍 自动化测试理论: 图片上的文字等等不能做测试,只能发现固定的bug 工具选择及介绍 浏览器驱动:找元素--核心:驱动(操作元素)--通过代码...

【es6进阶】如何使用Proxy实现自己的观察者模式
观察者模式(Observer mode)指的是函数自动观察数据对象,一旦对象有变化,函数就会自动执行。这里,我们是使用es6的proxy及reflect来实现这个效果。 实现效果 业务分析 源数据 const object2 {name: "张三"…...
住宅IP怎么在指纹浏览器设置运营矩阵账号
矩阵账号的运营已经成为了许多企业和个人推广策略中的重要一环。通过构建和管理多个社交媒体或电商平台的账号,可以有效地扩大品牌影响力,提高市场覆盖率。然而,随着平台对账号关联的限制越来越严格,如何安全、有效地运营这些矩阵…...

表格数据处理中大语言模型的微调优化策略研究
论文地址 Research on Fine-Tuning Optimization Strategies for Large Language Models in Tabular Data Processing 论文主要内容 这篇论文的主要内容是研究大型语言模型(LLMs)在处理表格数据时的微调优化策略。具体来说,论文探讨了以下…...
CentOS7 如何查看kafka topic中的数据
1. 确保 Kafka 服务运行 先检查 Kafka 和 Zookeeper 是否正在运行: systemctl status kafka systemctl status zookeeper 如果没有启动,先启动服务: systemctl start zookeeper systemctl start kafka 2. 进入 Kafka 安装目录 通常 …...

VRRP实现出口网关设备冗余备份
VRRP虚拟路由冗余 vrrp实现设备主备备份 Tips: VRRP能够在不改变组网的情况下,将多台路由器虚拟成一个虚拟路由器,通过配置虚拟路由器的IP地址为默认网关,实现网关的备份。协议版本: VRRPV2 (常用)和VRRPV3:VRRPV2仅适用于IPv4…...

超详细:Redis分布式锁
如何基于 Redis 实现一个最简易的分布式锁? 不论是本地锁还是分布式锁,核心都在于“互斥”。 在 Redis 中, SETNX 命令是可以帮助我们实现互斥。SETNX 即 SET if Not eXists (对应 Java 中的 setIfAbsent 方法),如果 key 不存在…...

Vue与React的Suspense组件对比
在Vue和React中都内置了Suspense组件,该组件用于处理异步组件加载。当Suspense包裹的实际组件内容尚未加载完成时会先展示后备内容,等待组件内容加载完成后再切换成实际组件内容。这可以显著提升用户体验,适用于大数据加载、组件懒加载等场景…...
Spring框架深度剖析:特性、安全与优化
文章目录 Spring框架简介主要特性1. 依赖注入(Dependency Injection, DI)2. 面向切面编程(Aspect-Oriented Programming, AOP)3. 声明式事务管理4. 强大的MVC框架5. 集成测试支持6. 多种数据访问技术的支持 安全性1. 认证…...

硬盘文件误删:全面解析、恢复方案与预防策略
一、硬盘文件误删现象概述 在日常使用电脑的过程中,硬盘文件误删是许多用户都曾遇到过的问题。这种意外的数据丢失,不仅可能让我们辛苦编辑的文档、珍贵的照片和视频等瞬间消失,还可能对工作和生活造成重大影响。硬盘文件误删,如…...

tcpdump抓包 wireShark
TCPdump抓包工具介绍 TCPdump,全称dump the traffic on anetwork,是一个运行在linux平台可以根据使用者需求对网络上传输的数据包进行捕获的抓包工具。 tcpdump可以支持的功能: 1、在Linux平台将网络中传输的数据包全部捕获过来进行分析 2、支持网络层…...

Android system_server进程
目录 一、system_server进程介绍 二、system_server进程启动流程 2.1 startBootstrapServices 2.2 startCoreServices 2.3 startOtherServices 2.4 startApexServices 三、如何使用系统服务 3.1 app进程调用系统服务 3.2 native进程调用系统服务 3.3 system_server进…...

Vue3+element-plus 实现中英文切换(Vue-i18n组件的使用)
1、前言 在 Vue 3 项目中结合 vue-i18n 和 Element Plus 实现中英文切换是一个常见的需求。下面是一个详细的步骤指南,帮助你完成这个任务。 安装引入 1. 安装依赖 首先,你需要安装 vue-i18n 和 Element Plus。 npm install vue-i18nnext element-p…...

【JVM】- 内存结构
引言 JVM:Java Virtual Machine 定义:Java虚拟机,Java二进制字节码的运行环境好处: 一次编写,到处运行自动内存管理,垃圾回收的功能数组下标越界检查(会抛异常,不会覆盖到其他代码…...
oracle与MySQL数据库之间数据同步的技术要点
Oracle与MySQL数据库之间的数据同步是一个涉及多个技术要点的复杂任务。由于Oracle和MySQL的架构差异,它们的数据同步要求既要保持数据的准确性和一致性,又要处理好性能问题。以下是一些主要的技术要点: 数据结构差异 数据类型差异ÿ…...

[10-3]软件I2C读写MPU6050 江协科技学习笔记(16个知识点)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16...

12.找到字符串中所有字母异位词
🧠 题目解析 题目描述: 给定两个字符串 s 和 p,找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义: 若两个字符串包含的字符种类和出现次数完全相同,顺序无所谓,则互为…...
数据库分批入库
今天在工作中,遇到一个问题,就是分批查询的时候,由于批次过大导致出现了一些问题,一下是问题描述和解决方案: 示例: // 假设已有数据列表 dataList 和 PreparedStatement pstmt int batchSize 1000; // …...
汇编常见指令
汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX(不访问内存)XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...

推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材)
推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材) 这个项目能干嘛? 使用 gemini 2.0 的 api 和 google 其他的 api 来做衍生处理 简化和优化了文生图和图生图的行为(我的最主要) 并且有一些目标检测和切割(我用不到) 视频和 imagefx 因为没 a…...

免费PDF转图片工具
免费PDF转图片工具 一款简单易用的PDF转图片工具,可以将PDF文件快速转换为高质量PNG图片。无需安装复杂的软件,也不需要在线上传文件,保护您的隐私。 工具截图 主要特点 🚀 快速转换:本地转换,无需等待上…...

基于Java+VUE+MariaDB实现(Web)仿小米商城
仿小米商城 环境安装 nodejs maven JDK11 运行 mvn clean install -DskipTestscd adminmvn spring-boot:runcd ../webmvn spring-boot:runcd ../xiaomi-store-admin-vuenpm installnpm run servecd ../xiaomi-store-vuenpm installnpm run serve 注意:运行前…...
Spring AI Chat Memory 实战指南:Local 与 JDBC 存储集成
一个面向 Java 开发者的 Sring-Ai 示例工程项目,该项目是一个 Spring AI 快速入门的样例工程项目,旨在通过一些小的案例展示 Spring AI 框架的核心功能和使用方法。 项目采用模块化设计,每个模块都专注于特定的功能领域,便于学习和…...