《排序算法全解析:从基础到优化,一文吃透八大排序!》

一、为什么我们需要读懂排序--不止于"排顺序"的核心价值

排序是计算机科学中最基础也是最核心的操作之一,看似只是将数据排成有序,实则贯穿我们生活中的每个角落,拼多多上的价格排序,搜索引擎上的权重排序,甚至是最常见的手机相册上的时间排序背后都依赖着排序算法的支撑
但大多数初学者往往会陷入"死记代码"的误区,而忽略了排序的本质--通过高效的比较与交换,降低数据的无序度

本文将从排序算法的设计思路,底层原理,时间复杂度以及适用场景来帮你彻底搞懂排序

核心对比总表:

屏幕截图 2026-01-20 172516

二、必学排序算法:底层逻辑+代码实现(附上详细注释)

注:以下排序默认是排升序

冒泡排序

核心思想:

通过重复的遍历数组,每次比较两两相邻的数据,若顺序正确就不交换,顺序错误就交换,每次遍历就完成一个数据的排序(最后一个数据成为最大/最小的数据)

特点:

稳定排序(相等元素顺序不变),时间复杂度O(N^2),空间复杂度O(1)

适用场景:

无实践意义,仅有教学意义

时间复杂度:

考虑最坏的情况:逆序
假设有n个数据,第一个数据最大,通过两两交换,要交换n-1次才能交换到最后一个,此时次大的数据被交换到第一个,最后一个数据已经确定,所以要交换n-2次才能交换到倒数第二个,依次类推,实际上是一个等差数列(n-1+n-2+n-3+……+1) = (n(n-1))/2,故时间复杂度为O(N^2)

代码实现:

点击查看代码
void Swap(int* x, int* y) {int tmp = *x;*x = *y;*y = tmp;
}void BubbleSort(int* a, int size) {for (int j = 0; j < size; j++) {int Flag = 0;for (int i = 0; i < size - j - 1; i++) {if (a[i] > a[i + 1]) {Flag = 1;Swap(&a[i], &a[i + 1]);}}//此时一次遍历没有两两交换,说明已经有序了if (Flag == 0) {break;}}
}

堆排序

核心思想:

先用向下调整法建大堆,此时堆顶元素是最大的数据,然后与最后一个元素交换,最后一个元素变成了最大的数据,注意size--,再向下调整法建堆,寻找次大的元素,继续交换,依次类推……

特点:

不稳定排序(会进行跨位置交换,可能打乱原相等数据的相对位置),时间复杂度为O(N*logN),空间复杂度为O(1)

适用场景:

数据量较大且不需要排序结果稳定的场景
可以解决TopK问题

点击查看代码
void GiveFile() {//建立文件const char* filepath = "randomdata.txt";FILE* fin = fopen(filepath, "w");if (fin == NULL) {perror("fopen():error");return ;}int size = 100000;for (int i = 0; i < size; i++) {int random = rand() + i;fprintf(fin, "%d\n", random);}fclose(fin);
}void FindTopK() {const char* filepath = "randomdata.txt";FILE* fout = fopen(filepath, "r");if (fout == NULL) {perror("fopen():error");return;}int k = 0;printf("请输入k:\n");scanf("%d", &k);//将前k个数放进了数组中int* a = (int*)malloc(k * sizeof(int));if (a == NULL) {perror("malloc fail");return;}for (int i = 0; i < k; i++) {fscanf(fout, "%d", &a[i]);}//调成小堆for (int i = (k - 2) / 2; i >= 0; i--) {AdjustDown(a, k, i);}//将文件中的数据依次与堆顶数据比较int tmp = 0;while (fscanf(fout, "%d", &tmp)==1) {if (tmp > a[0]) {a[0] = tmp;AdjustDown(a, k, 0);}}//这个时候已经获得了前k大的数,但不分先后int tmpk = k;//最后一次插入后整体不一定满足小堆AdjustDown(a, k, 0);//这个时候已经满足小堆,用堆排序for (int i = 0; i < tmpk;i++) {Swap(&a[0], &a[k - 1]);k--;AdjustDown(a, k, 0);}for (int i = 0; i < tmpk; i++) {printf("%d ", a[i]);}fclose(fout);
}//找出10万个数中前k大的数
int main() {srand((unsigned int)time(NULL));//方法一:建立大堆,取堆顶的数据,然后pop,用向下调整算法使堆顶数据成为第二大的,继续取……//这样的问题是空间复杂度为O(N)//方法二:建立前k个数的小堆,先把前k个数放进去,然后将剩下的数据依次与堆顶数据比较,如果比堆顶数据大,进栈,然后用向下调整法调成小堆//最后堆里的k个元素就是前k大的数(不分顺序)//还可以再用一次向下调整法调整至小堆,再用堆排序GiveFile();FindTopK();return 0;
}

时间复杂度:

向下调整建堆:

屏幕截图 2026-01-20 110150
排序:

屏幕截图 2026-01-20 111515

代码实现:

点击查看代码
void AdjustDwon(int* a, int size, int parent) {int morechild = 2 * parent + 1;while (morechild < size) {//找到较大子节点if (morechild + 1 < size && a[morechild] < a[morechild + 1]) {morechild++;}if (a[morechild] > a[parent]) {Swap(&a[morechild], &a[parent]);parent = morechild;morechild = 2 * parent + 1;}else {break;}}
}//时间复杂度为O(N*logN)
void HeapSort(int* a, int size) {//先用向下调整法建大堆int parent = (size - 2) / 2;while(parent >= 0) {AdjustDwon(a, size, parent);parent--;}int tmpsize = size;for (int i = 0; i < tmpsize; i++) {Swap(&a[0], &a[size - 1]);size--;AdjustDwon(a, size, 0);}
}

插入排序

核心思想:

end前面的数据已经实现了有序,新插入的数据需要与前面的数据依次比较,如果新数据较小,那么原来的数据往前挪,直到新数据比原数据大为止,从而实现了有序

特点:

稳定排序,时间复杂度为O(N2),适应性较好(实际上往往介于O(N2)与O(N)之间),空间复杂度为O(1)

适用场景:

小规模数据排序(如快排的小区间优化),近似有序数据排序

时间复杂度:

屏幕截图 2026-01-20 114001

代码实现:

点击查看代码
void InsertSort(int* a, int size) {//end前面的已经是有序了,然后将end+1与前面的依次比较for (int i = 0; i < size - 1; i++) {int end = i;int tmp = a[end + 1];while (end >= 0) {if (tmp < a[end]) {a[end + 1] = a[end];end--;}else {break;}}a[end + 1] = tmp;}
}

选择排序

核心思想:

多次遍历,找到最大值与最小值,将最大值与末尾值交换,将最小值与开头值交换

特点:

不稳定排序(涉及跨位置交换),时间复杂度为O(N^2),空间复杂度为O(1)

适用场景:

无实际意义,仅有教学意义

时间复杂度:

屏幕截图 2026-01-20 115900

适用场景:

适应性差,无法判断是否有序,时间复杂度一般都在O(N^2),仅具有教学意义

代码实现:

点击查看代码
void SelectSort(int* a, int size) {int begin = 0;int end = size - 1;//将最大与最小分别放在两边while (begin <= end) {int mini = begin;int maxi = begin;for (int i = begin + 1; i <= end; i++) {//应该是<=if (a[i] > a[maxi]) {maxi = i;}if (a[i] < a[mini]) {mini = i;}}Swap(&a[begin], &a[mini]);//应该用交换函数,否则会覆盖if (begin == maxi)maxi = mini;//这里begin可能与maxi相同,mini的值就会被交换走,//这里即使end==mini也没关系,因为不影响后序的排序Swap(&a[end], &a[maxi]);begin++;end--;}
}

希尔排序

核心思想:

其底层仍然是插入排序,但插入排序有一个缺点:在处理逆序或接近逆序的时候时间复杂度偏高,所以在插入排序前先进行预排序,使大的数尽量排在后面

特点:

不稳定排序,时间复杂度约为O(N^(1.3)),空间复杂度为O(1)

适用场景:

中等规模数据的高效排序,且对内存消耗要求较低

时间复杂度:

希尔排序的时间复杂度受增量序列的影响较大,选择合适的增量序列可以显著提高排序效率。作者水平有限,无法推导

代码实现:

点击查看代码
void ShellSort(int* a, int size) {//先预排序,把大的数据往后边放,把小的数据往前挪int gap = size;//当gap=1时就跟插入排序是一样的while (gap>1) {gap = gap / 3 + 1;//加1的目的是保证最后一次gap=1,从而实现插入排序for (int j = 0; j < gap; j++) {for (int i = j; i < size - gap; i += gap) {int end = i;int tmp = a[end + gap];while (end >= 0) {if (a[end] > tmp) {a[end + gap] = a[end];end -= gap;}else {break;}}a[end + gap] = tmp;}//这层循环是控制以gap为一组的交换}//循环gap次,把所有的组都插入交换一次}//多次以不同的gap值预排序,最后gap==1,插入排序
}

快排

核心思想:

屏幕截图 2026-01-20 143202

屏幕截图 2026-01-20 151336

单趟快排(代码实现):

点击查看代码
//霍尔的单趟快排
int QuickSort1(int* a, int left, int right) {int mid = GetMid(a, left, right);int key = left;Swap(&a[key], &a[mid]);int begin = left;int end = right;while (begin < end) {while (begin < end && a[end] >= a[key]) {end--;}while (begin < end && a[begin] <= a[key]) {begin++;}Swap(&a[begin], &a[end]);}Swap(&a[key], &a[begin]);return begin;
}//双指针法的单趟快排
int QuickSort2(int* a, int left,int right) {int key = left;int prev = left;int cur = left + 1;//cur指针是为了找比key小的数,找到了就先++prev然后与prev交换数据,cur++,没找到就cur++,prev不动    while(cur<=right) {if (a[cur] < a[key] && ++prev != cur) {Swap(&a[cur], &a[prev]);}cur++;}Swap(&a[key], &a[prev]);return prev;
}

特点:

不稳定排序,时间复杂度为O(N*logN),空间复杂度为O(1)

适用场景:

内存中数据的高效排序,且对排序稳定性没有要求

时间复杂度:

注:默认情况是选最左边的数字作为key

最优情况:每次选key都选到中间数字,即每次等长划分区间

屏幕截图 2026-01-20 144035
此时就如同树一般,递归深度为logN,每层都需要遍历一遍,时间为O(N),故时间复杂度为O(N*logN)

最坏情况:每次都选到最大或者最小的数作为key,每次划分会得到长度为n-1和0的子数组,此时递归的层数为N层,每层时间为O(N),故时间复杂度为O(N^2)
由此可见:选key是重中之重,下面介绍两种方式优化选key的方式
1、随机数选key:利用随机数选key,极大概率上避免了key选到极端值(最大或最小)的情况
2、三输取中法选key:从最左边和最右边和中间选一个中间的数,这样永远不可能选到最小或最大的数了
代码实现:

点击查看代码
int GetMid(int*a,int left, int right) {int mid = (left + right) / 2;if (a[left] > a[right]) {if (a[right] > a[mid])return right;else if (a[mid] > a[left])return left;elsereturn mid;}else {if (a[left] > a[mid])return left;else if (a[mid] > a[right])return right;elsereturn mid;}
}

代码实现:

递归版:

点击查看代码
void QuickSort(int* a, int left, int right) {if (left >= right)return;//小区间优化,如果最后只剩几个值了,如果继续递归就会比较浪费时间了。这个时候可以调用其他函数来排这几个数if (right - left + 1 < 10) {InsertSort(a + left, right - left + 1);//这里是对a+left以后的数据进行排序,所以要加left,注意}else {int mid = GetMid(a, left, right);//这是为了处理顺序的情况,如果使顺序的话,它会不断拆分成一个,然后回归,所以要使key不能最大也不能最小int key = mid;Swap(&a[key], &a[mid]);int begin = left;int end = right;while (begin < end) {while (begin < end && a[end] >= a[key]) {end--;}while (begin < end && a[begin] <= a[key]) {begin++;}Swap(&a[begin], &a[end]);}Swap(&a[begin], &a[key]);//分为三个区间: [key,begin-1] begin == end [end+1,right] QuickSort(a, left, begin - 1);QuickSort(a, end + 1, right);}
}

非递归版:
用栈来模拟递归的实现:利用栈的特性(后进先出)来保存左右区间

点击查看代码
#include "Stack.h"
//栈的实现详情请看上一期
void QuickSortNonR(int* a, int left, int right) {//用栈来保存区间ST st;STinit(&st);STpush(&st, right);STpush(&st, left);//栈中没有区间了才停下来while (!STempty(&st)) {int begin = STtop(&st);STpop(&st);int end = STtop(&st);STpop(&st);int key = QuickSort2(a,begin,end);//这里分成的是[begin,key - 1] key [key + 1,end]if (key + 1 < end) {//小于的是end,每次都不一样//push新的左右区间STpush(&st, end);STpush(&st, key + 1);}if ((key - 1) > begin) {STpush(&st, key - 1);STpush(&st, begin);}}STdes

快排的致命痛点:

屏幕截图 2026-01-20 195855

代码实现:

点击查看代码
//快排的三路划分
void QuickSort3(int* a,int left,int right) {if (left >= right)return;int begin = left;int key = a[left];int end = right;int cur = begin + 1;while (cur <= end) {if (a[cur] < key) {Swap(&a[cur], &a[begin]);cur++;begin++;}else if (a[cur] == key) cur++;else {Swap(&a[cur], &a[end]);end--;}}//此时分为三个区间[left,begin-1] [begin,end] [end+1,right]QuickSort3(a, left, begin - 1);QuickSort3(a, end+1,right);
}

归并排序

核心思想:

无限的二分数组,直到两两有序(只有一个值)然后开始归并
屏幕截图 2026-01-20 154555

特点:

稳定排序,时间复杂度为O(N*logN),空间复杂度为O(N)

适用场景:

需要稳定排序,数据量较大,或数据存储在外部存储器中

时间复杂度:

由于它基本上是均分数组,是完全二叉树,递归深度为logN层,每层都需要遍历一边,时间为O(N),故时间复杂度为O(N*logN)

代码实现:

递归版:

点击查看代码
void _MergeSort(int* a, int* tmp, int left, int right) {//当只有一个值了就有序了if (left >= right) {return;}int mid = (left + right) / 2;//注意:这里选区间有坑,只能这么选int begin1 = left, end1 = mid;int begin2 = mid + 1, end2 = right;_MergeSort(a, tmp, begin1, end1);_MergeSort(a, tmp, begin2, end2);//当两个数组有序的时候int i = begin1;//每次的i是从begin1开始的//只要有一个走完了就结束了while (begin1 <= end1 && begin2 <= end2) {if (a[begin1] < a[begin2]) {tmp[i++] = a[begin1++];}else {tmp[i++] = a[begin2++];}}while (begin2 <= end2) {//要取等号,否则单值会漏掉tmp[i++] = a[begin2++];}while (begin1 <= end1) {tmp[i++] = a[begin1++];}memcpy(a + left, tmp + left, sizeof(int) * (right - left + 1));//归并完了要拷贝回去,每次起点不一样
}
void MergeSort(int* a, int size) {int* tmp = (int*)malloc(sizeof(int) * size);if (tmp == NULL) {perror("malloc fail");return;}//每次malloc完都要检验,如果不开子函数,每次递归的时候都会malloc一个数组,浪费空间_MergeSort(a, tmp, 0,size - 1);free(tmp);tmp = NULL;
}
选区间时的坑:

屏幕截图 2026-01-20 155743
非递归版:

点击查看代码
void MergeSortNonR(int* a, int size) {int* tmp = (int*)malloc(sizeof(int) * size);if (tmp == NULL) {perror("malloc fail");return;}//每次malloc完都要检验int gap = 1;//gap是每组的个数,从一个开始,因为只有一个肯定有序while (gap < size) {int j = 0;//从一 一开始排,然后过渡到两两开始,是由gap来控制的for (int i = 0; i < size; i += 2 * gap) {int begin1 = i, end1 = i + gap - 1;int begin2 = i + gap, end2 = i + 2 * gap - 1;//因为此时只有[begin1,end1]已经是有序了,不需要再归并了if (begin2 >= size)break;//处理end2越界的问题,先把end2改成size-1再归并,这样就变成了[begin1,end1]与[begin2,size-1]的归并if (end2 >= size)end2 = size - 1;//只要有一个走完了就结束了while (begin1 <= end1 && begin2 <= end2) {if (a[begin1] < a[begin2]) {tmp[j++] = a[begin1++];}else {tmp[j++] = a[begin2++];}}while (begin2 <= end2) {//要取等号,否则单值会漏掉tmp[j++] = a[begin2++];}while (begin1 <= end1) {tmp[j++] = a[begin1++];}//需要一段一段拷贝,原因:当begin2 >= size的时候此时的end2已经超出size-1了拷贝的数量就不对了memcpy(a + i, tmp + i, sizeof(int) * (end2 - i + 1));}printf("\n");gap *= 2;}free(tmp);tmp = NULL;
}
代码实现中的坑:

屏幕截图 2026-01-20 161642

计数排序

核心思想:

新开一个数组,用新数组的下标来表示原数组的数据,遍历一遍原数组,每遇到原数组中的数据,新数组对应的下标的值就++,然后再遍历一边新数组,把新数组的值拷贝回原数组

特点:

非比较排序,时间复杂度为O(N + range),空间复杂度为O(N)

适用场景:

数据类型集中,数值范围远小于数据量(此时时间复杂度为O(N))

时间复杂度:

两次遍历,分别为O(N),O(range),故时间复杂度为O(N+range)

代码实现:

点击查看代码
void CountSort(int* a, int size) {//先遍历一遍找到最小值和最大值(相对映射)int mini = a[0], maxi = a[0];for (int i = 0; i < size; i++) {if (a[i] < mini)mini = a[i];if (a[i] > maxi)maxi = a[i];}int range = maxi - mini + 1;//calloc自动初始化为0//如果用malloc需要用memset手动初始化为0int* tmp = (int*)calloc(range,sizeof(int));if (tmp == NULL) {perror("calloc fail");return;}//放入tmp下标中for (int i = 0; i < size; i++) {//相对映射,若直接映射会浪费太多空间tmp[a[i] - mini]++;}//拷贝回原数组int j = 0;for (int i = 0; i < range; i++) {while (tmp[i]--) {a[j++] = i + mini;}}free(tmp);tmp = NULL;
}
相对映射: 先遍历出原数组的最大值与最小值,从而决定新数组的大小,原数组的数据-min值就是新数组对应的下标

归并排序的外排序

选归并的原因:

因为其他的排序都是用数组存储数据,要用下标去访问数据,但在磁盘文件中不方便访问,需要读写文件来访问,速度极慢

核心思路:

将一个大文件的数据放到file1和file2两个小文件中去,并用排序算法排成有序,然后用归并算法将file1和file2合成有序的大文件mfile,删除file1和file2,将mfile改名为file1,然后继续读文件到file2中,继续归并……

代码实现:

点击查看代码
//文件的外排序(用归并排序实现)//设置随机的数
void FileSet() {const char* filename = "data.txt";FILE* file = fopen(filename, "w");if (file == NULL) {perror("fopen fail");return;}//写入随机数据int size = 1000000;for (int i = 0; i < size; i++) {fprintf(file, "%d\n", rand() + i);}fclose(file);
}//把文件中的数读入新文件中,并排序
//返回实际读到的数据个数
int ReadNDataSortToFile(FILE* file, int n, const char* name) {//要是每次都打开文件的话文件指针又会重头开始了,所以要提前打开FILE* file1 = fopen(name, "w");if (file1 == NULL) {perror("fopen fail");return 0;}//把原文件读入临时的数组中int* a = (int*)calloc(n, sizeof(int));if (a == NULL) {perror("calloc fail");return 0;}int index = 0;//因为此时不一定能读满n个int x = 0;for (int i = 0; i < n; i++) {if (fscanf(file, "%d", &x)==EOF)break;a[index++] = x;//index此时是个数}if (index == 0) {free(a);a = NULL;//一定要free掉,不然会内存泄露return 0;}//将数组a排序QuickSortNonR(a, 0, index-1);//任意排序均可//然后把数组中的值写入file1中for (int i = 0; i < index; i++) {fprintf(file1, "%d\n", a[i]);}fclose(file1);free(a);a = NULL;return index;
}//将两个有序的文件归并在一起
void MergeSortToFile(const char* file1name, const char* file2name,const char* mfilename) {FILE* file1 = fopen(file1name, "r");if (file1 == NULL) {perror("fopen fail");return;}FILE* file2 = fopen(file2name, "r");if (file2 == NULL) {perror("fopen fail");return;}FILE* mfile = fopen(mfilename, "w");if (mfile == NULL) {perror("fopen fail");return;}//将file1和file2归并在一起int x1;int x2;int ret1 = fscanf(file1, "%d", &x1);int ret2 = fscanf(file2, "%d", &x2);while (ret1 !=EOF && ret2!=EOF) {//这里的ret1和ret2要更新if (x1<x2) {fprintf(mfile, "%d\n", x1);//要加换行ret1 = fscanf(file1, "%d", &x1);}else {fprintf(mfile, "%d\n", x2);ret2 = fscanf(file2, "%d", &x2);}}while (ret1 != EOF) {fprintf(mfile, "%d\n", x1);ret1 = fscanf(file1, "%d", &x1);}while (ret2!= EOF) {fprintf(mfile, "%d\n", x2);ret2 = fscanf(file2, "%d", &x2);}fclose(file1);fclose(file2);fclose(mfile);
}void FileTest() {srand((unsigned int)time(NULL));FileSet();const char* filename = "data.txt";FILE* file = fopen(filename, "r");if (file == NULL) {perror("fopen fail");return;}//将这文件的数据写入file1和file2中,分别排序,然后归并在一起const char* file1 = "file1.txt";const char* file2 = "file2.txt";const char* mfile = "mfile.txt";int m = 100000;//每次读入的数据个数ReadNDataSortToFile(file, m, file1);ReadNDataSortToFile(file, m, file2);while (1) {//将file1和file2归并在一起MergeSortToFile(file1, file2, mfile);//归并在一起后删除file1和file2remove(file1);remove(file2);//再将mfile名字改成file1,循环操作rename(mfile, file1);if (ReadNDataSortToFile(file, m, file2) == 0)break;}fclose(file);
}

排序测试

点击查看代码
#include"Sort.h"void SortTest() {srand((unsigned int)time(NULL));int N = 10000000;int* a1 = (int*)malloc(N * sizeof(int));int* a2 = (int*)malloc(N * sizeof(int));int* a3 = (int*)malloc(N * sizeof(int));int* a4 = (int*)malloc(N * sizeof(int));int* a5 = (int*)malloc(N * sizeof(int));int* a6 = (int*)malloc(N * sizeof(int));int* a7 = (int*)malloc(N * sizeof(int));int* a8 = (int*)malloc(N * sizeof(int));for (int i = 0; i < N; i++) {a1[i] = rand() + i+100;a2[i] = a1[i];a3[i] = a1[i];a4[i] = a1[i];a5[i] = a1[i];a6[i] = a1[i];a7[i] = a1[i];a8[i] = a1[i];}//冒泡排序int begin = clock();BubbleSort(a1, N);int end = clock();printf("BubbleSort:%d\n", end - begin);//堆排序begin = clock();HeapSort(a2,N);end = clock();printf("HeapSort:%d\n", end - begin);//插入排序begin = clock();InsertSort(a3,N);end = clock();printf("InsertSort:%d\n", end - begin);//希尔排序begin = clock();ShellSort(a4, N);end = clock();printf("ShellSort:%d\n", end - begin);//选择排序begin = clock();SelectSort(a5, N);end = clock();printf("SelectSort:%d\n", end - begin);//快排begin = clock();QuickSort(a6, 0,N-1);end = clock();printf("QuickSort:%d\n", end - begin);//归并排序begin = clock();MergeSort(a7, N);end = clock();printf("MergeSort:%d\n", end - begin);//计数排序begin = clock();CountSort(a8, N);end = clock();printf("CountSort:%d\n", end - begin);//验证是否排正确int Flag = 1;for (int i = 0; i < N; i++) {if (a8[i] != a7[i])Flag = 0;}if (Flag == 1) {printf("计数排序正确\n");}else {printf("计数排序错误\n");}
}

三、总结

数据量小吗?->插入排序
需要稳定排序?->归并排序/计数排序
数据在磁盘还是在内存?->磁盘选择归并,内存选快排
内存资源紧张吗?->原地排序(快排/希尔/堆排)

没有最好的排序算法,只有最适合的排序算法

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

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

相关文章

Linux命令大全-grep命令

一、简介grep(英文全拼: Global Regular Expression Print)命令用于查找文件里符合条件的字符串或正则表达式&#xff0c;并将符合条件的内容进行输出。二、语法语法&#xff1a;grep [选项]... PATTERN [FILE]...PATTERN&#xff1a;是一个基本正则表达式(缩写为BRE)&#xff…

ue c++编译报错解决

目录 e1696 无法打开 源 文件 "IMQTTClient.h" 解决方法&#xff1a; e1696 无法打开 源 文件 "IMQTTClient.h" 解决方法&#xff1a; 删除 目录&#xff1a; .vs Binaries Intermediate Saved 选中文件&#xff1a; MetahumancharacterHeiXi.uproje…

解析nanogpt - 详解

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

计算机毕业设计springboot线上票务系统app 基于Spring Boot的移动票务管理平台开发 Spring Boot框架下的线上票务系统设计与实现

计算机毕业设计springboot线上票务系统app_ck27e &#xff08;配套有源码 程序 mysql数据库 论文&#xff09; 本套源码可以在文本联xi,先看具体系统功能演示视频领取&#xff0c;可分享源码参考。随着互联网技术的飞速发展&#xff0c;线上票务系统已经成为人们日常生活中不可…

集合幂级数全家桶

集合幂级数 exp 求 \(e^{F(x)} = \sum\limits_{i \ge 0} \dfrac{F(x)^i}{i!}\),其中若 \(S \cap T = \varnothing\),则 \(x^S \times x^T = x^{S \cup T}\)。 定义二元函数 \(F(x, y) = \sum x^S y^{|S|} a_S\),这样…

计算机毕业设计springboot大气网格化治理智慧平台-报警处理子系统 基于SpringBoot的城市大气环境网格化智能预警与处置平台 SpringBoot驱动的空气质量网格监管报警协同系统

计算机毕业设计springboot大气网格化治理智慧平台-报警处理子系统9w1d1 &#xff08;配套有源码 程序 mysql数据库 论文&#xff09; 本套源码可以在文本联xi,先看具体系统功能演示视频领取&#xff0c;可分享源码参考。PM2.5爆表那天&#xff0c;整个城市像被按下了灰色滤镜。…

AtCoder Beginner Contest竞赛题解 | AtCoder Beginner Contest 440

​欢迎大家订阅我的专栏&#xff1a;算法题解&#xff1a;C与Python实现&#xff01; 本专栏旨在帮助大家从基础到进阶 &#xff0c;逐步提升编程能力&#xff0c;助力信息学竞赛备战&#xff01; 专栏特色 1.经典算法练习&#xff1a;根据信息学竞赛大纲&#xff0c;精心挑选…

近十届两院增选院士籍贯 / 出生地排行:苏浙皖湘鲁霸榜

整理了近十届两院增选院士的籍贯、出生地数据&#xff1a; ✅ 维度一&#xff1a;院士「籍贯」&#xff08;最能体现地域文教底蕴&#xff09; 籍贯人数 TOP20 核心榜单&#xff08;头部集中度极高&#xff09; 1、浙江宁波 28 人&#xff08;全国第一&#xff0c;70年的稳定输…

LeetCode 379 电话目录管理系统

文章目录摘要描述题解答案题解代码分析1. 数据结构的选择2. 初始化方法3. get() 方法&#xff1a;分配号码4. check() 方法&#xff1a;检查号码是否可用5. release() 方法&#xff1a;释放号码6. 为什么使用 Set Array 的组合&#xff1f;7. 边界情况处理示例测试及结果示例 …

量子计算模拟器性能基准测试方法论

随着量子算法在金融建模、药物研发等领域的应用突破&#xff0c;量子计算模拟器已成为经典计算机环境验证量子程序的核心工具。软件测试从业者亟需建立一套针对量子特性的标准化基准测试体系。本文旨在系统阐述测试框架的设计原则、关键性能指标及工具链实践方案&#xff0c;为…

基于微信小程序的电子元器件商城系统源码文档部署文档代码讲解等

课题介绍本课题旨在开发一款基于微信小程序的电子元器件商城系统&#xff0c;适配电子元器件品类多、规格杂、采购场景多元的特性&#xff0c;解决传统采购渠道分散、比价繁琐、库存查询不便等痛点。系统以微信小程序为前端载体&#xff0c;依托Node.js搭建后端服务&#xff0c…

【Linux 网络】拒绝传输卡顿!滑动窗口如何让数据 “跑赢” 等待?

一、滑动窗口滑动窗口大小&#xff1a;指的是无需等待确认应答而可以继续发送数据的最大值&#xff1b;注意&#xff1a;这里的无需等待确认应答&#xff0c;不是不要确认应答&#xff0c;而是暂时不要&#xff1b;站在发送方&#xff08;主机A 视角&#xff09;&#xff1a;图…

硬核干货:Checkpoint对齐诅咒与Timer风暴——Flink周期性反压的终极排查

第一章&#xff1a;那只准时敲门的“幽灵”——Checkpoint与其背后的IO风暴我们拿到的是一个极其诡异的现场&#xff1a;每30分钟一次&#xff0c;持续5分钟的反压。这不像是因为数据倾斜导致的“长尾”&#xff0c;也不像代码逻辑死循环导致的“猝死”。它太规律了&#xff0c…

基于微信小程序的付费自习室系统源码文档部署文档代码讲解等

课题介绍本课题聚焦付费自习室行业数字化需求&#xff0c;设计并实现一款基于微信小程序的付费自习室系统&#xff0c;解决传统自习室预约繁琐、计费不透明、座位管理低效等痛点。系统以微信小程序为前端交互入口&#xff0c;采用Node.js搭建后端服务&#xff0c;搭配MySQL数据…

基于微信小程序的高校毕业生公考助手系统源码文档部署文档代码讲解等

课题介绍本课题针对高校毕业生公考备考信息零散、规划混乱、刷题低效等痛点&#xff0c;设计并实现一款基于微信小程序的高校毕业生公考助手系统&#xff0c;为毕业生提供一站式公考备考服务。系统以微信小程序为前端载体&#xff0c;采用Node.js搭建后端服务&#xff0c;结合M…

边缘计算节点延迟专项测试实践指南

1. 测试概述与重要性 边缘计算节点的延迟直接影响实时应用性能&#xff08;如工业自动化、车联网&#xff09;&#xff0c;延迟过高可能导致业务中断或数据不一致。专项测试需评估端到端响应时间、抖动及丢包率等指标&#xff0c;确保节点在5G等低延迟场景下满足SLA要求&#…

大数据领域Kafka的性能调优实战

大数据领域Kafka的性能调优实战&#xff1a;从青铜到王者的进阶指南 关键词&#xff1a;Kafka性能调优、生产者优化、Broker配置、消费者调优、吞吐量与延迟 摘要&#xff1a;在大数据时代&#xff0c;Kafka作为分布式消息队列和流处理平台的"扛把子"&#xff0c;其性…

Flutter 2025 测试策略全景:从单元测试到混沌工程,构建坚不可摧的高质量应用 - 指南

Flutter 2025 测试策略全景:从单元测试到混沌工程,构建坚不可摧的高质量应用 - 指南pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; …

LLM Weekly(2026.1.5-2026.1.11)

网络资讯 ChatGPT 健康功能全新上线 OpenAI 推出了 ChatGPT Health,这是一个专属加密空间,可将用户的医疗记录和健康类应用程序与 ChatGPT 相连接,从而提供个性化的非诊断性健康指导。该服务采用数据隔离机制,健康相关对话内容不会用于模型训练,同时支持多重身份验证(MF…