【不看会后悔系列】排序之——文件归并【史上最全详解】~
文章目录
- 前言
- 一、何为文件归并?
- 二、文件归并思路分析
- 三、创造多数据文件
- 四、前置准备——堆排序
- 五、两个文件写入到第三个文件
- 六、读 N 个数据返回给文件,并返回读到数据的个数
- 七、文件归并
- 八、文件归并完整代码总结
- 1. 运行代码
- 2. 运行截图
- 总结
前言
学习了归并排序了之后,我们来了解一下文件是怎么归并的。、
要看归并排序请戳我~

一、何为文件归并?
文件归并外排序(External Sorting with Merge)是一种专门处理大规模数据的排序算法,适用于数据量大到无法一次全部加载到内存的情况。主要用于处理硬盘等外部存储设备上的数据,而不是内存中的数据。
外排序的核心思想:
-
排序阶段(分割数据):由于数据量过大,无法一次性全部放入内存,所以将数据分块处理。每次读取内存能够容纳的一部分数据,对这部分数据进行排序,然后将排序后的数据存储到临时文件中。重复这个过程,直到所有数据都被处理并生成多个有序的临时文件。
-
归并阶段(合并文件):将之前生成的多个有序临时文件按一定方式归并成一个大的有序文件。归并排序的特点是不需要随机访问数据,只需按顺序读入数据进行归并,因此特别适合外排序。
步骤总结:
- Step 1: 分割数据并对每个分块排序(生成多个有序的临时文件)。
- Step 2: 将这些有序的临时文件逐步归并,直到所有数据整合成一个完整的有序文件。
外排序与内排序的区别:
- 外排序:处理无法完全加载到内存中的数据,使用“排序-归并”策略,依赖外部存储设备。
- 内排序:处理能完全加载到内存中的数据,常用排序算法如快速排序、堆排序等都属于内排序。
归并排序作为一种适用于顺序读取数据的算法,可以同时用于内存中的排序和外存储的排序,因此在外排序中也广泛应用。
二、文件归并思路分析
假设这是我们未排序的文件
-
分块排序:
- 读取内存能容纳的
n个数据,进行排序。 - 将排序后的数据写入到
file1。 - 再次读取
n个数据,排序后写入到file2。

- 读取内存能容纳的
-
初步归并:
- 通过归并排序的思想,同时从
file1和file2中按顺序读取数据。 - 比较
file1和file2的当前值,将较小的值依次写入到mfile中。 - 继续此过程,直到
file1和file2的数据全部归并到mfile中,生成一个新的有序文件。

- 通过归并排序的思想,同时从
-
文件重命名和清理:
- 删除
file1和file2,释放存储空间。 - 将
mfile重命名为file1,以便后续继续归并。

- 删除
-
继续处理新的数据:
- 继续读取
n个新的数据进行排序,并将其写入到file2。 - 再次执行归并操作,将
file1和file2归并成一个新的有序文件,存入mfile。

- 继续读取
-
重复归并,直到结束:
- 重复步骤 2 和步骤 4,直到所有数据处理完毕。
- 最终归并后的有序文件存放在
file1中,完成整个排序过程。

文件归并的特点:
- 每次只需在内存中处理一小部分数据,避免内存溢出问题。
- 使用归并排序保证了数据在外存储中按顺序处理,高效完成排序。
三、创造多数据文件
思路如下:
-
定义随机数个数
n:int n = 1000000;- 定义
n为1000000,表示需要在文件中生成 100 万个随机数。
- 定义
-
初始化随机数种子:
srand(time(0));- 使用
srand(time(0))来初始化随机数种子,确保每次运行时生成的随机数序列不同。
- 使用
-
定义文件名:
const char* file = "data.txt"; const char* file1 = "file1"; const char* file2 = "file2";- 定义了三个文件路径,
data.txt用于存储生成的随机数,file1和file2用于后续归并排序中的临时文件。
- 定义了三个文件路径,
-
打开文件
data.txt(用于写入数据):FILE* fin = fopen(file, "w"); if (fin == NULL) {perror("fopen error");return; }- 使用
fopen以写入模式 (w) 打开data.txt,若打开失败,则输出错误信息并退出函数。
- 使用
-
生成并写入随机数:
for (int i = 0; i < n; i++) {int x = rand() + i;fprintf(fin, "%d\n", x); }- 使用
for循环生成n个随机数,并通过fprintf将它们逐行写入到data.txt文件中。 rand()用于生成随机数,并在每个随机数上加上当前循环索引i,以增加随机数的分布多样性。
- 使用
-
关闭文件
data.txt:fclose(fin);- 随机数写入完成后,关闭
data.txt文件。
- 随机数写入完成后,关闭
-
清空
file1和file2:FILE* f1 = fopen(file1, "w"); FILE* f2 = fopen(file2, "w"); if (f1 == NULL || f2 == NULL) {perror("fopen file1 or file2 fail!");return; }- 分别以写模式打开
file1和file2文件。如果文件不存在,则会创建;如果文件存在,则清空内容。
- 分别以写模式打开
-
关闭
file1和file2:fclose(f1); fclose(f2);- 清空完成后,关闭
file1和file2,准备后续排序时使用。
- 清空完成后,关闭
总结:
- 这个函数的核心任务是生成一个包含随机数的文件
data.txt,并准备两个空的文件file1和file2,为接下来的外部归并排序操作做准备。 - 通过这种方式,数据先被分批处理、排序并写入
file1和file2,最后通过归并的方式组合成有序文件。
像这样就创建成功了
代码如下:
// 创建有 N 个数据的文件,并同时创建 file1 和 file2
void CreatNData()
{// 随机数造数据int n = 1000000;srand(time(0));const char* file = "data.txt";const char* file1 = "file1";const char* file2 = "file2";// 打开文件(写数据)FILE* fin = fopen(file, "w");// 判断文件是否打开成功if (fin == NULL){perror("fopen error");return;}// 循环开始写数据for (int i = 0; i < n; i++){int x = rand() + i;fprintf(fin, "%d\n", x);}// 关闭大文件fclose(fin);// 清空 file1 和 file2,以便后续使用FILE* f1 = fopen(file1, "w");FILE* f2 = fopen(file2, "w");if (f1 == NULL || f2 == NULL){perror("fopen file1 or file2 fail!");return;}// 关闭 file1 和 file2fclose(f1);fclose(f2);
}
四、前置准备——堆排序
后面拿n个数据读取到file1和file2中的时候需要排序,我们这里使用堆排序
J桑前面讲过好多次堆排序,这里就直接给代码啦~
需要看堆排序戳我~~~
//先把堆排拿过来备用
void Swap(int* p1, int* p2)
{int tmp = *p1;*p1 = *p2;*p2 = tmp;
}
void AdjustDown(int* a, int n, int parent)
{int child = parent * 2 + 1;while (child < n){// 选出左右孩⼦中⼤的那⼀个if (child + 1 < n && a[child + 1] > a[child]){++child;}if (a[child] > a[parent]){Swap(&a[child], &a[parent]);parent = child;child = parent * 2 + 1;}else{break;}}
}
void HeapSort(int* a, int n)
{// 建堆 -- 向下调整建堆 -- O(N)for (int i = (n - 1 - 1) / 2; i >= 0; --i){AdjustDown(a, n, i);}// O(N*logN)int end = n - 1;while (end > 0){Swap(&a[end], &a[0]);AdjustDown(a, end, 0);--end;}
}
五、两个文件写入到第三个文件
这段代码通过归并排序的思想,将 file1 和 file2 中的数据按序合并到 mfile 中。具体流程如下:
- 打开文件:以读取模式打开
file1和file2,以写入模式打开mfile。 - 归并数据:通过循环从
file1和file2读取数据,比较大小后将较小的值写入mfile。 - 处理剩余数据:当一个文件的数据读完后,将另一个文件剩下的数据依次写入
mfile。 - 关闭文件:处理完成后,关闭所有文件。
这里简单解释一下 fscanf 的用法
fscanf发生错误时会返回EOF,因此我们可以用EOF来判断
代码如下:
// file1⽂件的数据和file2⽂件的数据归并到mfile⽂件中
void MergeFile(const char* file1, const char* file2, const char* mfile)
{//创立三个文件,以读的方式打开file1和file2,以写的方式打开mfileFILE* fout1 = fopen(file1, "r");if (fout1 == NULL){perror("fopen file1 fail!");exit(-1);}FILE* fout2 = fopen(file2, "r");if (fout2 == NULL){perror("fopen file2 fail!");exit(-1);}FILE* fin = fopen(mfile, "w");if (fin == NULL){perror("fopen mfile fail!");exit(-1);}// 这⾥跟内存中数组归并的思想完全类似,只是数据在硬盘⽂件中⽽已// 依次读取file1和file2的数据,谁的数据⼩,谁就往mfile⽂件中去写// file1和file2其中⼀个⽂件结束后,再把另⼀个⽂件未结束⽂件数据,// 依次写到mfile的后⾯int num1, num2;int ret1 = fscanf(fout1, "%d\n", &num1);int ret2 = fscanf(fout2, "%d\n", &num2);while (ret1 != EOF && ret2 != EOF){if (num1 < num2){fprintf(fin, "%d\n", num1);ret1 = fscanf(fout1, "%d\n", &num1);}else{fprintf(fin, "%d\n", num2);ret2 = fscanf(fout2, "%d\n", &num2);}}while (ret1 != EOF){fprintf(fin, "%d\n", num1);ret1 = fscanf(fout1, "%d\n", &num1);}while (ret2 != EOF){fprintf(fin, "%d\n", num2);ret2 = fscanf(fout2, "%d\n", &num2);}///打开文件后记得关闭fclose(fout1);fclose(fout2);fclose(fin);
}
六、读 N 个数据返回给文件,并返回读到数据的个数
这段代码的功能是从文件中读取 n 个数据,排序后再写入另一个文件,并返回实际读取到的数据个数。具体流程如下:
-
读取数据:
- 使用
fscanf从文件fout中读取整数,最多读取n个数据,存储在数组a中。 - 通过
i记录实际读取到的数据个数,循环读取直到达到n或文件结束。
- 使用
-
检查数据数量:
- 如果没有读取到任何数据,直接返回
0,表示读取失败或文件为空。
- 如果没有读取到任何数据,直接返回
-
堆排序:
- 如果读取到了数据,调用
HeapSort对数组a中的i个数据进行排序。
- 如果读取到了数据,调用
-
写入排序后的数据:
- 打开目标文件
file,并将排序后的数据逐行写入。 - 文件写入完成后关闭文件。
- 打开目标文件
-
返回值:
- 返回实际读取并排序的数据个数
i,用于后续处理。
- 返回实际读取并排序的数据个数
关键点:
- 数据读取使用
fscanf,按行读取整数。我们构建父本的时候也是按行%d\n形式的 - 使用堆排序
HeapSort对数据进行排序。 - 数据排序后写回到指定的
file文件中。
代码如下:
// 返回读取到的数据个数,并排序,读 N 个数据返回给文件,并返回读到数据的个数
int ReadNNumSortToFile(FILE* fout, int* a, int n, const char* file)
{//数据读到 x 中int x = 0;// i 表示读到数据的个数int i = 0;while (i < n && fscanf(fout, "%d\n", &x) != EOF){a[i++] = x;}//如果一个数据都没读到,不用排序了,返回0if (i == 0){return i;}//读到的数据堆排序HeapSort(a, i);//把排序过的数组放回文件中去FILE* fin = fopen(file, "w");if (fin == NULL){perror("fopen file fail!");exit(-1);}for (int j = 0; j < i; j++){fprintf(fin, "%d\n", a[j]);}//记得关闭文件fclose(fin);return i;
}
七、文件归并
该函数的目的是通过外部归并排序,将大文件 file 按照块处理,逐块排序并归并,最终生成一个有序文件。
开始之前,我们先来了解两个函数:
remove:
rename:
用这两个函数就可以有效删除和重命名我们的文件,合理运用返回值增强代码健壮性,还可以当作判断条件
-
文件打开:
FILE* fout = fopen(file, "r");- 以只读模式打开要排序的文件
file,如果打开失败,程序退出。
- 以只读模式打开要排序的文件
-
定义临时文件:
const char* file1 = "file1"; const char* file2 = "file2"; const char* mfile = "mfile";file1和file2用于存储分块后的数据,mfile是临时文件,存储归并后的数据。
-
内存分配:
int* a = (int*)malloc(sizeof(int) * n);- 为数组
a分配大小为n的内存空间,用于存储从文件中读取的数据。n是每次读取数据的大小,取决于内存可用空间。
- 为数组
-
数据分块并排序:
int readCount1 = ReadNNumSortToFile(fout, a, n, file1); int readCount2 = ReadNNumSortToFile(fout, a, n, file2);- 调用
ReadNNumSortToFile函数,从file中读取n个数据,排序后分别写入file1和file2。 - 读取的结果存储在
readCount1和readCount2,如果两个文件都没有数据,直接退出函数。
- 调用
-
循环归并:
while (1)- 进入循环,将
file1和file2中的数据归并到mfile中。
- 进入循环,将
-
文件处理:
-
归并:
MergeFile(file1, file2, mfile);- 调用
MergeFile函数,将file1和file2的内容按顺序归并到mfile。
- 调用
-
删除与重命名:
remove(file1); remove(file2); rename(mfile, file1);- 删除
file1和file2,然后将mfile重命名为file1,为下一次归并做准备。
- 删除
-
-
继续读取数据并归并:
if (ReadNNumSortToFile(fout, a, n, file2) == 0) {break; }- 再次读取
n个数据排序并存储到file2,如果无法再读取数据,说明归并结束,退出循环。
- 再次读取
-
结束处理:
fclose(fout); free(a);- 关闭文件并释放内存。
核心思想:
- 通过逐块读取数据到内存进行排序,随后将多个排序好的块文件进行归并,最终得到一个有序的文件。每次归并后的文件会循环处理,直至所有数据排序完成。
也就是我们一开始画的这张图,是我们整个文件归并的大框架
代码实现:
// MergeSortFile的第⼆个是每次取多少个数据到内存中排序,然后写到⼀个⼩⽂件进⾏归并
// 这个n给多少取决于我们有多少合理的内存可以利⽤,相对⽽⾔n越⼤,更多数据到内存中排序后,
// 再⾛⽂件归并排序,整体程序会越快⼀些。
void MergeSortFile(const char* file, int n)
{// 以写的方式打开文件 fileFILE* fout = fopen(file, "r");if (fout == NULL){perror("fopen file fail!");exit(-1);}// 定义三个文件 file1, file2, mfileconst char* file1 = "file1";const char* file2 = "file2";const char* mfile = "mfile";// 分割成⼀段⼀段数据,内存排序后写到,⼩⽂件int* a = (int*)malloc(sizeof(int) * n);if (a == NULL){perror("malloc fail!");exit(-1);}int readCount1 = ReadNNumSortToFile(fout, a, n, file1);int readCount2 = ReadNNumSortToFile(fout, a, n, file2);if (readCount1 == 0 && readCount2 == 0) {fclose(fout);free(a);return; // 如果两个文件都没有数据,直接返回}//循环归并获取元素while (1){// file1和file2⽂件归并到mfile⽂件中MergeFile(file1, file2, mfile);//删除file1和file2if (remove(file1) != 0 || remove(file2) != 0){perror("Error deleting file");exit(-1);}//重命名mfile为file1if (rename(mfile, file1) != 0){perror("Error renaming file");exit(-1);}// 读取N个数据到file2,继续⾛归并// 如果⼀个数据都没读到,则归并结束了if (ReadNNumSortToFile(fout, a, n, file2) == 0){break;}}printf("%s 文件成功排序到%s\n", file, file1);// 别忘了关闭文件,释放a空间fclose(fout);free(a);
}
八、文件归并完整代码总结
1. 运行代码
到这里我们所有的框架都搭建完了,现在要做的就是将他们结合起来
完整代码实现:
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>// 创建有 N 个数据的文件,并同时创建 file1 和 file2
void CreatNData()
{// 随机数造数据int n = 1000000;srand(time(0));const char* file = "data.txt";const char* file1 = "file1";const char* file2 = "file2";// 打开文件(写数据)FILE* fin = fopen(file, "w");// 判断文件是否打开成功if (fin == NULL){perror("fopen error");return;}// 循环开始写数据for (int i = 0; i < n; i++){int x = rand() + i;fprintf(fin, "%d\n", x);}// 关闭大文件fclose(fin);// 清空 file1 和 file2,以便后续使用FILE* f1 = fopen(file1, "w");FILE* f2 = fopen(file2, "w");if (f1 == NULL || f2 == NULL){perror("fopen file1 or file2 fail!");return;}// 关闭 file1 和 file2fclose(f1);fclose(f2);
}//先把堆排拿过来备用
void Swap(int* p1, int* p2)
{int tmp = *p1;*p1 = *p2;*p2 = tmp;
}
void AdjustDown(int* a, int n, int parent)
{int child = parent * 2 + 1;while (child < n){// 选出左右孩⼦中⼤的那⼀个if (child + 1 < n && a[child + 1] > a[child]){++child;}if (a[child] > a[parent]){Swap(&a[child], &a[parent]);parent = child;child = parent * 2 + 1;}else{break;}}
}
void HeapSort(int* a, int n)
{// 建堆 -- 向下调整建堆 -- O(N)for (int i = (n - 1 - 1) / 2; i >= 0; --i){AdjustDown(a, n, i);}// O(N*logN)int end = n - 1;while (end > 0){Swap(&a[end], &a[0]);AdjustDown(a, end, 0);--end;}
}// file1⽂件的数据和file2⽂件的数据归并到mfile⽂件中
void MergeFile(const char* file1, const char* file2, const char* mfile)
{//创立三个文件,以读的方式打开file1和file2,以写的方式打开mfileFILE* fout1 = fopen(file1, "r");if (fout1 == NULL){perror("fopen file1 fail!");exit(-1);}FILE* fout2 = fopen(file2, "r");if (fout2 == NULL){perror("fopen file2 fail!");exit(-1);}FILE* fin = fopen(mfile, "w");if (fin == NULL){perror("fopen mfile fail!");exit(-1);}// 这⾥跟内存中数组归并的思想完全类似,只是数据在硬盘⽂件中⽽已// 依次读取file1和file2的数据,谁的数据⼩,谁就往mfile⽂件中去写// file1和file2其中⼀个⽂件结束后,再把另⼀个⽂件未结束⽂件数据,// 依次写到mfile的后⾯int num1, num2;int ret1 = fscanf(fout1, "%d\n", &num1);int ret2 = fscanf(fout2, "%d\n", &num2);while (ret1 != EOF && ret2 != EOF){if (num1 < num2){fprintf(fin, "%d\n", num1);ret1 = fscanf(fout1, "%d\n", &num1);}else{fprintf(fin, "%d\n", num2);ret2 = fscanf(fout2, "%d\n", &num2);}}while (ret1 != EOF){fprintf(fin, "%d\n", num1);ret1 = fscanf(fout1, "%d\n", &num1);}while (ret2 != EOF){fprintf(fin, "%d\n", num2);ret2 = fscanf(fout2, "%d\n", &num2);}///打开文件后记得关闭fclose(fout1);fclose(fout2);fclose(fin);
}// 返回读取到的数据个数,并排序,读 N 个数据返回给文件,并返回读到数据的个数
int ReadNNumSortToFile(FILE* fout, int* a, int n, const char* file)
{//数据读到 x 中int x = 0;// i 表示读到数据的个数int i = 0;while (i < n && fscanf(fout, "%d\n", &x) != EOF){a[i++] = x;}//如果一个数据都没读到,不用排序了,返回0if (i == 0){return i;}//读到的数据堆排序HeapSort(a, i);//把排序过的数组放回文件中去FILE* fin = fopen(file, "w");if (fin == NULL){perror("fopen file fail!");exit(-1);}for (int j = 0; j < i; j++){fprintf(fin, "%d\n", a[j]);}//记得关闭文件fclose(fin);return i;
}// MergeSortFile的第⼆个是每次取多少个数据到内存中排序,然后写到⼀个⼩⽂件进⾏归并
// 这个n给多少取决于我们有多少合理的内存可以利⽤,相对⽽⾔n越⼤,更多数据到内存中排序后,
// 再⾛⽂件归并排序,整体程序会越快⼀些。
void MergeSortFile(const char* file, int n)
{// 以写的方式打开文件 fileFILE* fout = fopen(file, "r");if (fout == NULL){perror("fopen file fail!");exit(-1);}// 定义三个文件 file1, file2, mfileconst char* file1 = "file1";const char* file2 = "file2";const char* mfile = "mfile";// 分割成⼀段⼀段数据,内存排序后写到,⼩⽂件int* a = (int*)malloc(sizeof(int) * n);if (a == NULL){perror("malloc fail!");exit(-1);}int readCount1 = ReadNNumSortToFile(fout, a, n, file1);int readCount2 = ReadNNumSortToFile(fout, a, n, file2);if (readCount1 == 0 && readCount2 == 0) {fclose(fout);free(a);return; // 如果两个文件都没有数据,直接返回}//循环归并获取元素while (1){// file1和file2⽂件归并到mfile⽂件中MergeFile(file1, file2, mfile);//删除file1和file2if (remove(file1) != 0 || remove(file2) != 0){perror("Error deleting file");exit(-1);}//重命名mfile为file1if (rename(mfile, file1) != 0){perror("Error renaming file");exit(-1);}// 读取N个数据到file2,继续⾛归并// 如果⼀个数据都没读到,则归并结束了if (ReadNNumSortToFile(fout, a, n, file2) == 0){break;}}printf("%s 文件成功排序到%s\n", file, file1);// 别忘了关闭文件,释放a空间fclose(fout);free(a);
}int main()
{//CreatNData();// 一次排100000个数据MergeSortFile("data.txt", 100000);return 0;
}
2. 运行截图
我们来运行一下吧~
先创建数据

来到我们文件中,可以看到我们初始数据,还有file1,fiel2都创建好了。
再来运行排序

打开我们的文件,可以看到在file1中数据排好了升序,代表文件归并成功~
数据太多了,J桑就不都给大家看啦~
总结
到这里,我们文件归并的内容就结束啦~
最重要的是要先搭建出文件归并的框架,像这样大事化小的思路,然后先把框架化为代码,再去补充其他需要用到的函数~
那么,就谢谢大家啦~

相关文章:
【不看会后悔系列】排序之——文件归并【史上最全详解】~
文章目录 前言一、何为文件归并?二、文件归并思路分析三、创造多数据文件四、前置准备——堆排序五、两个文件写入到第三个文件六、读 N 个数据返回给文件,并返回读到数据的个数七、文件归并八、文件归并完整代码总结1. 运行代码2. 运行截图 总结 前言 学习了归并排…...
安全点的应用场景及其原理详解
引言 在Java虚拟机(JVM)运行的过程中,有些时刻,系统需要暂停所有正在运行的线程,以执行某些全局操作或确保数据的一致性。这些暂停线程的时刻被称为**“安全点”**(Safepoint)。尽管安全点最广…...
计算机各专业2025毕业设计选题推荐【各专业 | 最新】
计算机各专业2025毕业设计选题推荐 Java、Python、Vue、PHP、小程序、安卓、大数据、爬虫、可视化、机器学习、深度学习 文末有联系方式~~~ 1.Java 基于Java的在线购物系统设计与实现Java开发的图书管理系统基于Spring Boot的社交媒体平台Java实现的移动健康应用在线学习平…...
【Python报错已解决】IndexError: index 0 is out of bounds for axis 1 with size 0
🎬 鸽芷咕:个人主页 🔥 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想,就是为了理想的生活! 专栏介绍 在软件开发和日常使用中,BUG是不可避免的。本专栏致力于为广大开发者和技术爱好者提供一个关于BUG解决的经…...
SpringGateway(网关)微服务
一.启动nacos 1.查看linux的nacos是否启动 docker ps2.查看是否安装了nacos 前面是你的版本,后面的names是你自己的,我们下面要启动的就是这里的名字。 docker ps -a3.启动nacos并查看是否启动成功 二.创建网关项目 1.创建idea的maven项目 2.向pom.x…...
jQuery面试题:(第三天)
8.你在jQuery中使用过哪些插入节点的方法,它们的区别是什么? 答:append(),appendTo(),prepend(),prependTo(),after(),insertAfter() before(),insertBefore() 内添加 1.append()在文档内添加元素 2.appendTo()把匹配的元素添加到对象里 3.prepend()…...
聊聊国内首台重大技术装备(2)
上次,介绍了《首台(套)重大技术装备推广应用指导目录(2024年版)》中介绍的硅外延炉,湿法清洗机,氧化炉,见文章: 《聊聊国内首台重大技术装备(1)》…...
python 实现rayleigh quotient瑞利商算法
rayleigh quotient瑞利商算法介绍 瑞利商(Rayleigh Quotient)算法在多个领域,如线性代数、计算机视觉和机器学习等,都有重要的应用。瑞利商定义为函数 R ( A , x ) ( x H A x ) / ( x H x ) R(A, x) (x^H Ax) / (x^H x) R(A,x)…...
Java Web应用升级故障案例解析
在一次Java Web应用程序的优化升级过程中,从Tomcat 7.0.109版本升级至8.5.93版本后,尽管在预发布环境中验证无误,但在灰度环境中却发现了一个令人困惑的问题:新日志记录神秘“失踪”。本文深入探讨了这一问题的排查与解决过程&…...
Java类和对象、自定义包、static、代码块、方法重写
目录 1.类和对象 2.this指针 3.对象的构造和初始化 3.1默认初始化 3.2就地初始化 3.3构造初始化 3.4IDEA快速填充 3.5使用this简化 3.6初始化的总结 4.包的引入 4.1包的概念 4.2导入包中的类 4.3自定义包 5.static修饰 6.代码块的划分 7.方法重写 1.类和对象 使…...
【系统代码】招投标采购一体化管理系统,JAVA+vue
前言: 随着互联网和数字技术的不断发展,企业采购管理逐渐走向数字化和智能化。数字化采购平台作为企业采购管理的新模式,能够提高采购效率、降低采购成本、优化供应商合作效率,已成为企业实现效益提升的关键手段。系统获取在文末…...
基于yolov8深度学习的120种犬类检测与识别系统python源码+onnx模型+评估指标曲线+精美GUI界面目标检测狗类检测犬类识别系统
【算法介绍】 基于YOLOv8深度学习的120种犬类检测与识别系统是一款功能强大的工具,该系统利用YOLOv8深度学习框架,通过21583张图片的训练,实现了对120种犬类的精准检测与识别。 该系统基于Python与PyQt5开发,具有简洁的UI界面&a…...
UNI-APP_iOS开发技巧之:跳转到TestFlight或者App Store
有的时候我们的应用可能需要上TestFlight或者App Store,更新升级就需要跳到TestFlight里面。方法如下: 跳转到TestFlight: itms-beta://itunes.apple.com/app/你的AppID 跳转到AppStore: itms-apps://itunes.apple.com/app/你的AppIDhttps://airp…...
基于SSM+Vue技术的定制式音乐资讯平台
文未可获取一份本项目的java源码和数据库参考。 一、选题的背景与意义: 随着个人计算机的普及和互联网技术的日渐成熟,网络正逐渐成为人们获取信息及消费的主要渠道。然而在当前这个信息时代,网络中的信息种类和数量呈现爆炸性增长的趋势&a…...
Spring依赖注入和注解驱动详解和案例示范
在 Spring 框架中,依赖注入(Dependency Injection, DI)和注解驱动(Annotation-Driven)是其核心机制,它们为 Spring 应用提供了灵活性和可扩展性。依赖注入简化了对象间的依赖管理,而注解驱动则通…...
网络通信——OSPF协议(基础篇)
这里基础是因为没有讲解OSPF中的具体算法过程,以及其中很多小细节。后续会更新。 目录 一.OSPF的基础信息 二.认识OSPF中的Router ID 三.OSPF中的三张表 四.OSPF中的度量方法(计算开销值) 五. OSPF选举DR和BDR(就是这个区域…...
Kubernetes从零到精通(15-安全)
目录 一、Kubernetes API访问控制 1.传输安全(Transport Security) 2.认证(Authentication) 2.1 认证方式 2.2 ServiceAccount和普通用户的区别 2.3 ServiceAccount管理方式 自动ServiceAccount示例 手动ServiceAccount示例 3.鉴权 (Authorization) 3.1鉴权方式 3.2 …...
《蓝桥杯算法入门》(C/C++、Java、Python三个版本)24年10月出版
推荐:《算法竞赛》,算法竞赛大全书,网购:京东 天猫 当当 文章目录 《蓝桥杯算法入门》内容简介本书读者对象作者简介联系与交流《蓝桥杯算法入门 C/C》版目录 《蓝桥杯算法入门 Java》版目录 《蓝桥杯算法入门 Python》版目录 …...
Soar项目中添加一条新的SQL审核规则示例
soar是一个开源的SQL规则审核工具,是一个go语言项目,可以直接编译构建成一个可执行程序,而且是一个命令行工具,我们可以利用archey来调用soar进行sql规则审核以及sql的分析,包括执行计划的查看及sql建议等。 soar中已…...
RISC-V开发 linux下GCC编译自定义指令流程笔记
第一步:利用GCC提供了内嵌汇编的功能可以在C代码中直接内嵌汇编语言 第二步:利用RSIC-V的中的.insn模板进行自定义指令的插入 第三步:RISC-V开发环境的搭建 C语言插入汇编 GCC提供了内嵌汇编的功能可以在C代码中直接内嵌汇编语言语句方便了…...
springboot 百货中心供应链管理系统小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,百货中心供应链管理系统被用户普遍使用,为方…...
土地利用/土地覆盖遥感解译与基于CLUE模型未来变化情景预测;从基础到高级,涵盖ArcGIS数据处理、ENVI遥感解译与CLUE模型情景模拟等
🔍 土地利用/土地覆盖数据是生态、环境和气象等诸多领域模型的关键输入参数。通过遥感影像解译技术,可以精准获取历史或当前任何一个区域的土地利用/土地覆盖情况。这些数据不仅能够用于评估区域生态环境的变化趋势,还能有效评价重大生态工程…...
【HTTP三个基础问题】
面试官您好!HTTP是超文本传输协议,是互联网上客户端和服务器之间传输超文本数据(比如文字、图片、音频、视频等)的核心协议,当前互联网应用最广泛的版本是HTTP1.1,它基于经典的C/S模型,也就是客…...
python报错No module named ‘tensorflow.keras‘
是由于不同版本的tensorflow下的keras所在的路径不同,结合所安装的tensorflow的目录结构修改from语句即可。 原语句: from tensorflow.keras.layers import Conv1D, MaxPooling1D, LSTM, Dense 修改后: from tensorflow.python.keras.lay…...
Spring是如何解决Bean的循环依赖:三级缓存机制
1、什么是 Bean 的循环依赖 在 Spring框架中,Bean 的循环依赖是指多个 Bean 之间互相持有对方引用,形成闭环依赖关系的现象。 多个 Bean 的依赖关系构成环形链路,例如: 双向依赖:Bean A 依赖 Bean B,同时 Bean B 也依赖 Bean A(A↔B)。链条循环: Bean A → Bean…...
Java毕业设计:WML信息查询与后端信息发布系统开发
JAVAWML信息查询与后端信息发布系统实现 一、系统概述 本系统基于Java和WML(无线标记语言)技术开发,实现了移动设备上的信息查询与后端信息发布功能。系统采用B/S架构,服务器端使用Java Servlet处理请求,数据库采用MySQL存储信息࿰…...
比较数据迁移后MySQL数据库和OceanBase数据仓库中的表
设计一个MySQL数据库和OceanBase数据仓库的表数据比较的详细程序流程,两张表是相同的结构,都有整型主键id字段,需要每次从数据库分批取得2000条数据,用于比较,比较操作的同时可以再取2000条数据,等上一次比较完成之后,开始比较,直到比较完所有的数据。比较操作需要比较…...
深度学习之模型压缩三驾马车:模型剪枝、模型量化、知识蒸馏
一、引言 在深度学习中,我们训练出的神经网络往往非常庞大(比如像 ResNet、YOLOv8、Vision Transformer),虽然精度很高,但“太重”了,运行起来很慢,占用内存大,不适合部署到手机、摄…...
快速排序算法改进:随机快排-荷兰国旗划分详解
随机快速排序-荷兰国旗划分算法详解 一、基础知识回顾1.1 快速排序简介1.2 荷兰国旗问题 二、随机快排 - 荷兰国旗划分原理2.1 随机化枢轴选择2.2 荷兰国旗划分过程2.3 结合随机快排与荷兰国旗划分 三、代码实现3.1 Python实现3.2 Java实现3.3 C实现 四、性能分析4.1 时间复杂度…...
PydanticAI快速入门示例
参考链接:https://ai.pydantic.dev/#why-use-pydanticai 示例代码 from pydantic_ai import Agent from pydantic_ai.models.openai import OpenAIModel from pydantic_ai.providers.openai import OpenAIProvider# 配置使用阿里云通义千问模型 model OpenAIMode…...













