归并排序:数据排序的高效之道
🧑 博主简介:CSDN博客专家,历代文学网(PC端可以访问:https://literature.sinhy.com/#/literature?__c=1000,移动端可微信小程序搜索“历代文学”)总架构师,
15年
工作经验,精通Java编程
,高并发设计
,Springboot和微服务
,熟悉Linux
,ESXI虚拟化
以及云原生Docker和K8s
,热衷于探索科技的边界,并将理论知识转化为实际应用。保持对新技术的好奇心,乐于分享所学,希望通过我的实践经历和见解,启发他人的创新思维。在这里,我希望能与志同道合的朋友交流探讨,共同进步,一起在技术的世界里不断学习成长。
技术合作请加本人wx(注明来自csdn):foreast_sea
归并排序:数据排序的高效之道
一、引言
在当今数字化时代,数据处理的规模和复杂性呈指数级增长。无论是处理海量的商业数据、科学研究中的实验数据,还是日常应用程序中的用户信息,排序算法都扮演着至关重要的角色。排序能够将无序的数据转换为有序的序列,从而使得数据的查找、分析和处理变得更加高效和便捷。
归并排序作为一种经典且高效的排序算法,在众多领域都有着广泛的应用。它基于“分治”这一强大的思想策略,通过将大规模的问题逐步分解为更小的子问题,然后分别解决这些子问题,最后将子问题的解合并起来得到原问题的解。这种思想不仅在排序算法中大放异彩,在许多其他复杂的算法设计场景中也被频繁借鉴。
想象一下,在一个大型电商平台的订单处理系统中,每天都有海量的订单数据需要按照订单时间、金额或者客户优先级等进行排序。归并排序能够快速而稳定地对这些数据进行整理,使得商家可以清晰地了解订单的顺序,从而更好地安排发货、库存管理等后续工作。又比如在基因测序领域,大量的基因片段数据需要按照特定的顺序进行排列组合,归并排序可以高效地完成这一任务,为后续的基因分析和疾病研究提供有力支持。
在本文,我们将深入探讨归并排序的原理、详细剖析其代码实现,并全面分析它的时间复杂度、空间复杂度以及其他特性,还会将其与其他常见的排序算法进行对比,从而让您全方位地了解归并排序这一重要的数据处理工具。
二、归并排序的原理
(一)分治思想的核心
归并排序的核心在于“分治”。它将一个未排序的数组不断地分割成更小的子数组,直到每个子数组只包含一个元素。这就像是把一个大任务逐步拆解成一个个极小的、易于处理的子任务。例如,对于一个包含 8 个元素的数组 [5, 3, 8, 2, 9, 1, 7, 4]
,首先会被分割成两个子数组 [5, 3, 8, 2]
和 [9, 1, 7, 4]
,然后这两个子数组又会继续被分割,[5, 3, 8, 2]
会变成 [5, 3]
和 [8, 2]
,[9, 1, 7, 4]
会变成 [9, 1]
和 [7, 4]
,如此继续,直到每个子数组都只有一个元素,如 [5]
、[3]
、[8]
、[2]
、[9]
、[1]
、[7]
、[4]
。
(二)合并的巧妙过程
当子数组都分割到最小单位后,就开始了合并的过程。合并是归并排序的关键步骤,它将两个已经排序的子数组合并成一个更大的排序数组。比如有两个已排序的子数组 [2, 5]
和 [3, 8]
,我们创建一个新的空数组来存储合并后的结果。首先比较两个子数组的第一个元素,即 2 和 3,因为 2 较小,所以将 2 放入新数组,然后 [2, 5]
子数组的指针后移一位。接着比较 5 和 3,3 较小,将 3 放入新数组,[3, 8]
子数组指针后移。再比较 5 和 8,5 较小,放入新数组,此时 [2, 5]
子数组的元素已全部处理完,直接将 [3, 8]
子数组剩余的 8 放入新数组,最终得到合并后的排序数组 [2, 3, 5, 8]
。
(三)归并排序算法
归并排序根据 “分而治之” 原则运行:
首先,我们将要排序的元素分为两半。然后,将生成的子数组再次划分 - 直到创建长度为 1 的子数组:
现在,两个子数组已合并,以便从每对子数组创建一个排序数组。在最后一步中,合并原始数组的两半,以便对整个数组进行排序。
在下面的示例中,您将看到两个子数组如何合并为一个。
合并排序 合并示例
合并本身很简单:对于这两个数组,我们定义一个合并索引,它首先指向相应数组的第一个元素。显示这一点的最简单方法是使用示例(箭头表示合并索引):
将比较合并指针上的元素。两个中较小的一个(示例中的 1)被附加到一个新数组中,并且指向该元素的指针向右移动了一个字段:
现在,将再次比较指针上方的元素。这次 2 小于 4,因此我们将 2 附加到新数组中:
现在指针位于 3 和 4 上。3 更小,并附加到目标数组中:
现在 4 是最小的元素:
现在是 5:
在最后一步中,将 6 附加到新数组中:
两个排序的子数组被合并到排序的最终数组中。
三、归并排序的作用
(一)数据有序化的利器
归并排序的最主要作用就是将无序的数据转换为有序的数据。在很多数据处理场景中,有序的数据能够极大地提高数据查询和处理的效率。例如在数据库查询中,如果数据是按照特定的字段(如主键、索引字段)进行排序的,那么在进行范围查询、等值查询时,数据库引擎可以利用排序的特性快速定位到目标数据,减少查询的时间复杂度。
(二)为其他算法提供基础
归并排序得到的有序数据还可以作为其他更复杂算法的基础。比如在一些搜索算法中,有序的数据可以使用二分搜索等高效的搜索策略。在图像处理领域,对图像像素数据进行排序后,可以更方便地进行图像的边缘检测、特征提取等操作,因为有序的数据结构能够让算法更有规律地处理图像中的信息。
四、归并排序的使用场景
(一)大规模数据处理
在处理大规模数据时,归并排序的优势尤为明显。由于其时间复杂度为 O ( n log n ) O(n\log n) O(nlogn),即使数据量非常庞大,它也能够在相对合理的时间内完成排序任务。例如在大数据分析平台中,需要对海量的用户行为数据、日志数据等进行排序以便进行后续的分析挖掘,归并排序可以有效地处理这些数据,为数据分析提供有序的数据基础。
(二)稳定性要求高的场景
归并排序是一种稳定的排序算法,这意味着在排序过程中,相等元素的相对顺序不会改变。在一些对数据顺序稳定性有严格要求的场景中,归并排序是首选。比如在金融交易系统中,对于同一时间发生的多笔交易,如果按照交易金额进行排序,并且要求相同金额的交易按照交易时间的先后顺序排列,归并排序就能够很好地满足这一需求,确保交易数据的排序既按照金额有序,又不会打乱相同金额交易的时间顺序。
五、归并排序的代码实现
(一)Java 代码示例
以下是归并排序的 Java
代码实现:
public class MergeSort {// 归并排序的入口方法,接收一个数组作为参数public static void mergeSort(int[] arr) {// 调用递归的归并排序方法,传入数组、起始索引 0 和结束索引数组长度 - 1mergeSort(arr, 0, arr.length - 1);}// 递归的归并排序方法,用于对指定范围内的数组进行排序private static void mergeSort(int[] arr, int left, int right) {// 如果左索引小于右索引,说明子数组中至少有两个元素,需要继续分割if (left < right) {// 计算中间索引,用于将数组分割成两部分int mid = (left + right) / 2;// 对左半部分子数组进行递归排序mergeSort(arr, left, mid);// 对右半部分子数组进行递归排序mergeSort(arr, mid + 1, right);// 合并两个已排序的子数组merge(arr, left, mid, right);}}// 合并两个已排序子数组的方法private static void merge(int[] arr, int left, int mid, int right) {// 计算左子数组的长度int leftLen = mid - left + 1;// 计算右子数组的长度int rightLen = right - mid;// 创建临时数组来存储左子数组和右子数组的元素int[] leftArr = new int[leftLen];int[] rightArr = new int[rightLen];// 将原数组中的左子数组元素复制到临时左子数组for (int i = 0; i < leftLen; i++) {leftArr[i] = arr[left + i];}// 将原数组中的右子数组元素复制到临时右子数组for (int j = 0; j < rightLen; j++) {rightArr[j] = arr[mid + 1 + j];}// 初始化合并索引,分别指向左子数组和右子数组的起始位置int leftPos = 0;int rightPos = 0;// 初始化合并后的数组索引,指向合并后数组的起始位置int mergeIndex = left;// 比较左子数组和右子数组的元素,将较小的元素放入原数组while (leftPos < leftLen && rightPos < rightLen) {if (leftArr[leftPos] <= rightArr[rightPos]) {arr[mergeIndex] = leftArr[leftPos];leftPos++;} else {arr[mergeIndex] = rightArr[rightPos];rightPos++;}mergeIndex++;}// 如果左子数组还有剩余元素,将其全部放入原数组while (leftPos < leftLen) {arr[mergeIndex] = leftArr[leftPos];leftPos++;mergeIndex++;}// 如果右子数组还有剩余元素,将其全部放入原数组while (rightPos < rightLen) {arr[mergeIndex] = rightArr[rightPos];rightPos++;mergeIndex++;}}
}
在上述代码中:
mergeSort
方法是对外公开的入口方法,它接收一个数组并调用递归的mergeSort
方法开始排序过程,传入数组的起始索引 0 和结束索引arr.length - 1
。- 递归的
mergeSort
方法首先检查子数组是否至少有两个元素,如果是,则计算中间索引mid
,将数组分割成左右两部分,然后分别对左右子数组进行递归排序,最后调用merge
方法合并两个已排序的子数组。 merge
方法首先创建两个临时数组来存储左右子数组的元素,然后通过循环比较两个临时数组中的元素,将较小的元素放入原数组中对应的位置,当其中一个临时数组的元素全部处理完后,将另一个临时数组剩余的元素全部放入原数组。
(二)Python 代码示例
def merge_sort(arr):# 如果数组长度大于 1,则进行排序if len(arr) > 1:# 计算中间索引mid = len(arr) // 2# 分割左子数组left_half = arr[:mid]# 分割右子数组right_half = arr[mid:]# 递归地对左子数组进行归并排序merge_sort(left_half)# 递归地对右子数组进行归并排序merge_sort(right_half)# 初始化索引,分别用于左子数组、右子数组和合并后的数组i = j = k = 0# 比较左子数组和右子数组的元素,将较小的元素放入原数组while i < len(left_half) and j < len(right_half):if left_half[i] <= right_half[j]:arr[k] = left_half[i]i += 1else:arr[k] = right_half[j]j += 1k += 1# 如果左子数组还有剩余元素,将其全部放入原数组while i < len(left_half):arr[k] = left_half[i]i += 1k += 1# 如果右子数组还有剩余元素,将其全部放入原数组while j < len(right_half):arr[k] = right_half[j]j += 1k += 1# 测试归并排序
arr = [5, 3, 8, 2, 9, 1, 7, 4]
merge_sort(arr)
print(arr)
在 Python
代码中:
- 首先判断数组长度是否大于 1,如果是则计算中间索引
mid
,将数组分割成左右两半。 - 然后分别递归地对左右子数组进行归并排序。
- 接着通过循环比较左右子数组的元素,将较小的元素放入原数组
arr
中,使用三个索引i
、j
、k
分别跟踪左子数组、右子数组和合并后数组的位置。 - 最后处理左右子数组剩余元素的情况,将它们依次放入原数组。
六、归并排序的时间复杂度分析
(一)分割过程的时间消耗
在归并排序中,分割过程是不断地将数组一分为二。对于一个包含 n n n 个元素的数组,每次分割都将问题规模减半。设分割的次数为 k k k,则有 n = 2 k n = 2^k n=2k,通过对数运算可得 k = log 2 n k=\log_2 n k=log2n。每次分割的操作时间复杂度相对较低,可以看作是常数时间,所以分割过程总的时间复杂度为 O ( log n ) O(\log n) O(logn)。
(二)合并过程的时间消耗
合并过程是将两个已排序的子数组合并成一个更大的排序数组。在合并时,对于长度为 n n n 的数组,需要遍历每个元素一次,所以合并过程的时间复杂度为 O ( n ) O(n) O(n)。
(三)总体时间复杂度
由于归并排序的分割过程时间复杂度为 O ( log n ) O(\log n) O(logn),合并过程时间复杂度为 O ( n ) O(n) O(n),并且在每一层的分割后都需要进行合并操作,所以总的时间复杂度为 O ( n log n ) O(n\log n) O(nlogn)。这意味着无论输入数组是有序、逆序还是随机排列,归并排序的时间复杂度都保持在 O ( n log n ) O(n\log n) O(nlogn) 这一相对高效的水平。
七、归并排序的空间复杂度分析
(一)临时数组的空间需求
在归并排序的合并过程中,需要创建临时数组来存储左右子数组的元素。在最坏的情况下,当对一个包含 n n n 个元素的数组进行排序时,临时数组的大小可能达到 n n n 个元素的规模。例如,在最后一次合并时,左右子数组的长度之和可能接近 n n n。
(二)总体空间复杂度
因此,归并排序的空间复杂度为 O ( n ) O(n) O(n),这是因为在排序过程中需要额外的空间来存储临时数组中的元素。与一些原地排序算法(如冒泡排序、插入排序在某些优化情况下)相比,归并排序需要更多的额外空间,但它换来的是更高效的时间复杂度。
八、归并排序的其他特性
(一)稳定性
归并排序是一种稳定的排序算法。在合并过程中,当左右子数组的元素相等时,先将左子数组的元素放入合并后的数组。这就保证了相等元素在排序前后的相对顺序不会改变。例如,对于数组 [(3, 'a'), (3, 'b'), (5, 'c')]
,按照元素的第一个值进行排序时,归并排序会确保 (3, 'a')
在 (3, 'b')
之前,即使它们的第一个值相等。
(二)并行性
归并排序具有一定的并行性潜力。由于其分治的特性,可以将不同的子数组分割任务分配给不同的处理器核心或者线程来并行处理。例如,在对一个非常大的数组进行排序时,可以将数组分割成多个子数组,然后让多个线程同时对这些子数组进行归并排序,最后再将各个线程排序好的子数组合并起来。不过,在实际实现并行归并排序时,需要考虑线程同步、负载均衡等问题,以确保并行计算的效率。
九、归并排序与其他排序算法的对比
(一)与冒泡排序对比
冒泡排序是一种简单的比较排序算法,它的时间复杂度在最坏情况下为 O ( n 2 ) O(n^2) O(n2),平均情况下也为 O ( n 2 ) O(n^2) O(n2)。而归并排序的时间复杂度为 O ( n log n ) O(n\log n) O(nlogn),在大规模数据排序时,归并排序的效率远远高于冒泡排序。例如,当对 10000 个元素进行排序时,冒泡排序可能需要进行大量的元素比较和交换操作,时间消耗巨大,而归并排序则能够在相对较短的时间内完成排序任务。
(二)与插入排序对比
插入排序在最好情况下(数组已经部分有序)时间复杂度为 O ( n ) O(n) O(n),但在最坏和平均情况下时间复杂度为 O ( n 2 ) O(n^2) O(n2)。归并排序在任何情况下都保持 O ( n log n ) O(n\log n) O(nlogn) 的时间复杂度。而且插入排序是一种原地排序算法,空间复杂度为 O ( 1 ) O(1) O(1),而归并排序空间复杂度为 O ( n ) O(n) O(n)。在数据量较小且数组可能已经部分有序的情况下,插入排序可能表现较好,但对于大规模数据,归并排序更具优势。
(三)与快速排序对比
快速排序在平均情况下时间复杂度为 O ( n log n ) O(n\log n) O(nlogn),并且它是一种原地排序算法,空间复杂度在平均情况下为 O ( log n ) O(\log n) O(logn)。然而,快速排序在最坏情况下时间复杂度会退化为 O ( n 2 ) O(n^2) O(n2),例如当数组已经有序或者逆序时。而归并排序始终保持 O ( n log n ) O(n\log n) O(nlogn) 的时间复杂度,并且是稳定的。在数据随机分布且对稳定性要求不高的情况下,快速排序可能因为其原地特性和较好的平均性能而更常用,但在稳定性要求高或者数据可能出现最坏情况的场景下,归并排序则是更好的选择。
十、总结
归并排序作为一种经典的排序算法,以其高效的时间复杂度 O ( n log n ) O(n\log n) O(nlogn)、稳定的排序特性以及分治的巧妙思想,在数据处理领域占据着重要的地位。
相关文章:
归并排序:数据排序的高效之道
🧑 博主简介:CSDN博客专家,历代文学网(PC端可以访问:https://literature.sinhy.com/#/literature?__c1000,移动端可微信小程序搜索“历代文学”)总架构师,15年工作经验,…...
分布式训练(记录)
为什么要分布式训练? 单机训练有物理上限: 显存不够(大模型根本放不下) 单机计算慢(数据量一多就耗时太长) 多卡并行性不高 分布式训练的常见方式 Data Parallel(数据并行) 每个G…...
vue3中使用拖拽组件vuedragable@next
vue3中使用拖拽组件vuedragablenext 官网传送门 下载 npm install vuedraggablenext基本使用 <script setup> import draggable from vuedraggable import { ref } from vue const list ref([{ id:1,name:第一个 },{ id:2,name:第二个 },{ id:3,name:第三个 }, ]) <…...
Oracle、MySQL、PostgreSQL三大数据库对比分析
Oracle、MySQL、PostgreSQL 三大数据库的对比分析,结合 Java SpringBoot 项目开发 的实际场景,重点说明分库分表、主从复制的实现难度及案例。 一、数据库核心对比 1. 核心区别与适用场景 维度OracleMySQLPostgreSQL定位企业级商业数据库轻量级开源数据…...
java八股之并发编程
1.java线程和操作系统线程之间的区别? 现在java线程本质上是操作系统线程,java中采用的是一对一的线程模型(一个用户线程对应一个内核进程) 2.什么是进程和线程? 1.进程是操作系统一次执行,资源分配和调度的…...
Qt 入门 5 之其他窗口部件
Qt 入门 5 之其他窗口部件 本文介绍的窗口部件直接或间接继承自 QWidget 类详细介绍其他部件的功能与使用方法 1. QFrame 类 QFrame类是带有边框的部件的基类。它的子类包括最常用的标签部件QLabel另外还有 QLCDNumber、QSplitter,QStackedWidget,QToolBox 和 QAbstractScrol…...
Linux系统之----冯诺依曼结构
1.简要描述 冯诺依曼体系结构是现代计算机的基本设计思想,其核心理念是将计算机的硬件和软件统一为一个整体,通过存储程序的方式实现计算。冯诺依曼体系结构的核心思想是通过存储程序实现自动计算,其五大部件协同工作,奠定了现代…...
C++11新特性
目录 引入 C11新特性 统一的初始化列表 一切皆可{}初始化 std::initializer_list 统一的声明 auto decltype nullptr 范围for STL新增容器 STL新增容器接口 左值引用和右值引用 左值和右值 左值引用和右值引用 右值引用的优势(移动语义) 右值引用的使用场景 …...
492Q 型气缸盖双端面铣削组合铣床总体设计
一、引言 492Q 型气缸盖是发动机的重要组成部分,其双端面的加工精度对发动机的性能和可靠性有着重要影响。设计一款适用于 492Q 型气缸盖双端面铣削的组合铣床,能够提高加工效率和质量,满足发动机生产的需求。 二、总体设计要求 加工精度&…...
《软件设计师》复习笔记(4.2)——关系代数、函数依赖、范式
目录 一、关系代数 基本运算 笛卡尔积() 投影(π) 选择(σ) 自然连接(⋈) 真题示例: 二、函数依赖 基本概念 Armstrong公理系统 键与约束 三、范式ÿ…...
IO流(二)
一、字符流 使用字节流可以读取文件中的字节数据。但是如果文件中有中文使用字节流来读取,就有可能读到半个汉字的情况,这样会导致乱码。虽然使用读取全部字节的方法不会出现乱码,但是如果文件过大又不太合适。 所以Java专门为我们提供了另…...
#Linux动态大小裁剪以及包大小变大排查思路
1 动态库裁剪 库分为动态库和静态库,动态库是在程序运行时才加载,静态库是在编译时就加载到程序中。动态库的大小通常比静态库小,因为动态库只包含了程序需要的函数和数据,而静态库则包含了所有的函数和数据。静态库可以理解为引入…...
天梯赛数据结构合集
1.集合操作:PTA | 程序设计类实验辅助教学平台 主要是注意set的取交集操作,AC代码: #include<bits/stdc.h> using namespace std; int n,m,k; set<int> a[60]; int main(){cin>>n;for(int i1;i<n;i){cin>>m;for…...
pdfjs库使用记录1
import React, { useEffect, useState, useRef } from react; import * as pdfjsLib from pdfjs-dist; // 设置 worker 路径 pdfjsLib.GlobalWorkerOptions.workerSrc /pdf.worker.min.js; const PDFViewer ({ url }) > { const [pdf, setPdf] useState(null); const […...
LIMS引领综合质检中心数字化变革,赋能质量强国战略
在质量强国战略的深入推进下,我国综合质检机构迎来了前所未有的发展机遇,同时也面临着诸多严峻挑战。随着检测领域从传统的食品药品监督向环境监测、新材料检测等新兴领域不断拓展,跨领域协同管理的复杂度呈指数级增长。作为提升产品质量的关…...
MySQL+Redis实战教程:从Docker安装部署到自动化备份与数据恢复20250418
MySQLRedis实战教程:从Docker安装部署到自动化备份与数据恢复 一、前言 在企业应用中,对MySQL和Redis运维的要求越来越高: 不能仅是启动就算部署运行稳定、隔离、访问控制、备份恢复、安全可靠,才是 企业级的基本功能 本文将手…...
嵌入式音视频开发指南:从MPP框架到QT实战全解析
嵌入式音视频开发指南:从MPP框架到QT实战全解析 一、音视频技术全景概述 1.1 技术演进里程碑 2003-2010年:标清时代(H.264/AVC + RTMP)2011-2018年:高清时代(H.265/HEVC + WebRTC)2019-至今:智能时代(AV1 + AI编解码 + 低延迟传输)1.2 现代音视频技术栈 #mermaid-s…...
如何使用Python进行自动化的系统管理?
Python已经成为系统管理员最流行的编程语言之一,因为它简单、灵活,并且广泛支持各种系统管理任务。无论您是自动执行重复性任务,管理文件和目录,还是处理用户权限,Python都提供了一组强大的工具来简化您的工作流程。 …...
拆机装机,通电主板亮灯风扇不转无法开机解决办法
电源开机线 重启线 usb耳机模块 灯线 看来电源没问题 参考https://zhidao.baidu.com/question/83939532/answer/2321171868.html 买了个新主板过几天到看看会不会好...
IntelliSense 已完成初始化,但在尝试加载文档时出错
系列文章目录 文章目录 系列文章目录前言一、原因二、使用步骤 前言 IntelliSense 已完成初始化,但在尝试加载文档时出错 File path: E:\QtExercise\DigitalPlatform\DigitalPlatform\main\propertyWin.ui Frame GUID:96fe523d-6182-49f5-8992-3bea5f7e6ff6 Frame …...
SuperMap iClient3D for WebGL 如何加载WMTS服务
在 SuperMap iClient3D for WebGL 中加载WMTS服务时,参数配置很关键!下面我们详细介绍如何正确填写参数,确保影像服务完美加载。 一、数据制作 对于上述视频中的地图制作,此处不做讲述,如有需要可访问:Onl…...
[密码学实战]基于Python的国密算法与通用密码学工具箱
引言 在当今数字化浪潮中,信息安全已成为个人隐私保护与商业机密守护的核心议题。作为一位在密码学领域深耕多年的技术实践者,我深谙密码学工具在构建数字安全防线中的关键作用。正是基于这份认知与责任,我倾力打造了一款全方位、高性能的密…...
[密码学实战]详解gmssl库与第三方工具兼容性问题及解决方案
[密码学实战]详解gmssl库与第三方工具兼容性问题及解决方案 引言 国密算法(SM2/SM3/SM4)在金融、政务等领域广泛应用,但开发者在集成gmssl库实现SM2签名时,常遇到与第三方工具(如OpenSSL、国密网关)验证不…...
LIB-ZC, 一个跨平台(Linux)平台通用C/C++扩展库, stream 流操作
LIB-ZC, 一个跨平台(Linux)平台通用C/C扩展库, stream 流操作 lib-zc 封装了流操作命名空间 zcc基础类 stream(基类), iostream(io流封装) class stream 介绍 连接相关 // 都是虚函数, 为 iostream 等做准备virtual inline bool connect(const char *destination) { return …...
从零开始解剖Spring Boot启动流程:一个Java小白的奇幻冒险之旅
大家好呀!今天我们要一起探索一个神奇的话题——Spring Boot的启动流程。我知道很多小伙伴一听到"启动流程"四个字就开始头疼,别担心!我会用最通俗易懂的方式,带你从main()方法开始,一步步揭开Spring Boot的…...
概率多假设跟踪(PMHT):多目标跟踪中的概率软关联与高效跟踪算法解析
一、PMHT 的起源与核心定位 (一)背景 在多目标跟踪中,传统算法面临以下瓶颈: JPDA:单帧局部最优关联,无法处理跨帧长时间断联,且假设目标数固定(如雷达跟踪中预设目标数范围&…...
4.信号和槽|存在意义|信号和槽的连接方式|信号和槽断开|lambda表达式|信号和槽优缺点(C++)
信号和槽存在意义 所谓的信号槽,终究要解决的问题,就是响应用户的操作 信号槽,其实在GUI开发的各种框架中,是一个比较有特色的存在 其他的GUI开发框架,搞的方式都要更简洁一些~~ 网页开发 (js dom api) 网…...
电脑 BIOS 操作指南(Computer BIOS Operation Guide)
电脑 BIOS 操作指南 电脑的BIOS界面(应为“BIOS”)是一个固件界面,允许用户配置电脑的硬件设置。 进入BIOS后,你可以进行多种设置,具体包括: 1.启动配置 启动顺序:设置从哪个设备启动&#x…...
Scrapeless Scraping Browser: A high-concurrency automation solution for AI
介绍:升级无缝抓取浏览器的并发能力 作为 Scrapeless 的开发者和创始团队,我们对人工智能自动化的未来充满真诚的热情。我们的使命是创建一个真正为 AI 设计的自动化浏览器。在过去的几年中,从 Browserless.io 到众多云服务供应商推出的“浏…...
Java项目—— 拼图小游戏(进阶版)
项目需求 在拼图小游戏基础版的基础上,完成下列要求: 一、实现更换拼图图片功能 1,给美女,动物,运动菜单按钮添加单击事件(动作监听) 2,当我们点击了美女之后,就会从13…...
解析:深度优先搜索、广度优先搜索和回溯搜索
一、深度优先搜索(DFS) 1. 原理 思想:从起始节点出发,顺着一条路径不断深入,直到到达目标或无路可走,然后回溯到最近的分支点,继续探索其他分支。 应用场景:路径查找、连通性检测、…...
探索大语言模型(LLM):循环神经网络的深度解析与实战(RNN、LSTM 与 GRU)
一、循环神经网络(RNN) 1.1 基本原理 循环神经网络之所以得名,是因为它在处理序列数据时,隐藏层的节点之间存在循环连接。这意味着网络能够记住之前时间步的信息,并利用这些信息来处理当前的输入。 想象一下…...
从零开始开发 MCP Server
作者:张星宇 在大型语言模型(LLM)生态快速演进的今天,Model Context Protocol(MCP)作为连接 AI 能力与真实世界的标准化协议,正逐步成为智能体开发的事实标准。该协议通过定义 Resources&#…...
Oracle日志系统之重做日志和归档日志
Oracle日志系统之重做日志和归档日志 重做日志归档日志 本文讨论Oracle日志系统中对数据恢复非常重要的两个日志:重做日志和归档日志。 重做日志 重做日志,英文名Redo Log,顾名思义,是用来数据重做的,主要使用场景是事…...
嵌入式开发--STM32G4系列硬件CRC支持MODBUS和CRC32
需求 在项目中,需要用到MODBUS CRC16校验,也要用到CRC32的校验,出于效率的考虑,准备用硬件CRC。 CRC 16的参数模型有很多种,我这里用的是MODBUS,对于不同的参数模型,会有不同的参数设置和初值&a…...
基于尚硅谷FreeRTOS视频笔记——4—多任务处理
目录 多任务处理 任务调度 任务的调度策略 优先级不同 优先级相同 多任务处理 通俗来讲就是 能够在同一时间 同时 进行多个任务的处理,这就时多任务处理。 但是,单核处理器一次只能处理一个任务,就是说在while中,任务们只能…...
中小型及初创企业如何实现数字化转型?
在当今动态的商业环境中,财务团队开始肩负起推动企业数字化转型的重任,即从传统的财务规划系统稳步迈向基于商业智能平台和以创新技术为驱动的解决方案领域。这些举措有望提高运营和分析效率,同时依托数据驱动的决策机制,帮助企业…...
java输出、输入语句
先创建一个用于测试的java 编写程序 #java.util使java标准库的一个包,这里拉取Scanner类 import java.util.Scanner;public class VariableTest {public static void main(String[] args) {#创建一个 Scanner 对象Scanner scanner new Scanner(System.in);System.…...
Python基础知识语法归纳总结(数据类型-1)
Python基础知识&语法归纳总结(数据类型) 一、Python基本数据类型 尤其注意,Python中的变量不需要特定的去声明,每个变量在使用前都必须对其进行赋值,它没有类型,我们所说的“类型”是变量所指的内存中对…...
Spring数据访问全解析:ORM整合与JDBC高效实践
目录 一、Spring ORM集成深度剖析 🌟 ORM模块架构设计 核心集成特性: 整合MyBatis示例配置: 二、Spring JDBC高效实践指南 🌟 传统JDBC vs Spring JDBC对比 🌟 JdbcTemplate核心操作示例 批量操作优化…...
哪种电脑更稳定?Mac?Windows?还是云电脑? 实测解密
随着科技的发展进步,电脑已成为当下各类群体的必备产品之一,它的妙用有很多,无论是学生党、打工人还是已经退休的人群或都离不开它的存在。然而,电脑虽好却也差异很大、不同品牌、不同系统、不同配置、不同价位的统统都会有区别。…...
【AI模型学习】关于写论文——论文的审美
文章目录 一、“补丁法”(Patching)1.1 介绍1.2 方法论1.3 实例 二、判断工作的价值2.1 介绍2.2 详细思路2.3 科研性vs工程性 三、novelty以及误区3.1 介绍3.2 举例 看了李沐老师的读论文系列后,总结三个老师提到的有关课题研究和论文写作的三…...
【面经】杭州产链数字科技一面
1.介绍一下自己 面试官您好!我叫***,目前是就读于****计算机科学与技术专业的一名学生。我平时在学校也自学了编程相关的知识,比如Java基础、Springboot、SpringCloud,关系型数据库Mysql,非关系型数据库Redisÿ…...
微信小程序调用yolo目标检测模型
目录 后端 前端微信小程序 完整代码 后端 利用Flask,调用目标检测模型,后端代码如下。 # flask_yolo.py from flask import Flask, request, jsonify from ultralytics import YOLO from PIL import Imageapp Flask(__name__) model_path best.p…...
vmware17 虚拟机 ubuntu22.04 桥接模式,虚拟机无法接收组播消息
问题描述: 在一个项目中,宿主机win10中,使用的vmware17pro 虚拟机安装的ubuntu22.04,按照网上的教程使用Qt绑定组播消息,在另外一个Ubuntu工控机上发送用wiresahrk抓包的组播消息 sudo tcpreplay -i enp1s0 --loop0 y…...
Kaggle-Bag of Words Meets Bags of Popcorn-(二分类+NLP+Bert模型)
Bag of Words Meets Bags of Popcorn 题意: 有很多条电影评论记录,问你每一条记录是积极性的评论还是消极性的评论。 数据处理: 1.首先这是文件是zip形式,要先解压,注意sep ‘\t’。 2.加载预训练的 BERT 分词器 …...
数字信号处理技术架构与功能演进
数字信号处理(DSP)是通过数字运算实现信号分析、变换、滤波及调制解调的技术领域,其发展过程与技术应用如下: 一、定义与核心功能 技术定义:通过算法将模拟信号转换为数字形式进行处理,具有高精度、可编程…...
IaaS架构剖析、场景实践
一、什么是 IaaS 1.1 定义 Infrastructure as a Service(IaaS,基础设施即服务)是一种按需、弹性提供计算、存储、网络和安全等底层 IT 资源的云服务模式。用户通过 API、CLI 或 Web 控制台即可在几分钟内创建、扩容或释放资源,而…...
国产之光DeepSeek架构理解与应用分析02
本专栏 国产之光DeepSeek架构理解与应用分析-CSDN博客 国产之光DeepSeek架构理解与应用分析02-CSDN博客 前置的一些内容理解 GPU TPU NPU的区别? 设计目的 GPU:最初是为了加速图形渲染而设计的,用于处理图像和视频数据,以提供高…...
EDID结构
EDID DDC通讯中传输显示设备数据 VGA , DVI 的EDID由128字节组成,hdmi的EDID增加扩展块128字节。扩展快的内容主要是和音频属性相关的,DVI和vga没有音频,hdmi自带音频,扩展快数据规范按照cea-861x标准。 Edid为了让pc或其他的图像…...