当前位置: 首页 > article >正文

【数据结构】与排序算法鏖战5天,我终于搞懂了排序的思路和实现--排序算法大全的保姆级攻略

目录一排序的概念及分类二排序算法的实现1插入排序intsert sort_1,核心思路_2,代码实现_3,总结2希尔排序Shell sort_1,核心思路_2,代码实现_3,总结3选择排序Select sort_1,核心思想_2,代码实现_3,总结4堆排序Heap sort第一步建小堆方法一向上调整建小堆方法二向下调整建小堆第二步排序5冒泡排序(Bubble sort)_1,核心思想:_2,代码实现_3,总结6快速排序Quick sort_1,核心思想_2,代码实现_3,时间和空间效率_4,优化方法三数取中法和小区间优化_5,先后指针法实现单趟排序_6,非递归实现快速排序7归并排序 Merge sort_1,核心思想_2,代码实现_3,时间和空间效率_4,非递归实现归并排序8,计数排序Counting sort_1,核心思想_2,代码实现_3,时间和空间效率三各种排序总结及稳定一排序的概念及分类排序就是将将给定的一串数据进行从小到大或者从大到小进行排列。二排序算法的实现1插入排序intsert sort_1,核心思路将数组分成两个两个部分一个为已排序部分一个为未排序的部分默认数组中的第一个数为已排序部分然后将未排序部分的第一个数字依次排入到已排序的部分直到排序到最后一个数未排序部分消失。图例展示将有序数组中的最后一个元素的下表记录为end将无序部分的第一个元素的下标记录为tmp,将tmp所指向的元素和end及end前面的元素从后往前依次进行比较如果前面的元素大就向后移动一位如果小于就停止比较。_2,代码实现//插入排序 void Insertsort(int* a, int n) { for (int i 0; i n - 1; i) { int end i; //end的范围为[0,n-2] int tmp a[end 1]; //进行后移 while (end 0 tmp a[end]) //注意防止越界访问 { a[end 1] a[end]; end--; } //后移完进行插入 a[end 1] tmp; } }_3,总结元素越接近有序直接插入排序的时间效率越高时间复杂度最坏的情况数组逆序每一个数都要遍历一遍前面的数1234……n-1 n*(n-1)/2 - 1时间复杂度为O(n^2)空间复杂度没有开辟任何新的空间O(1)2希尔排序Shell sort_1,核心思路希尔排序也称为缩小增量排序是对直接插入排序的优化先进行预排序使得序列基本有序再进行直接插入排序。预排序先将序列划分几个小序列再对这几个小序列分别进行直接插入排序。分析相比于直接插入进行预排序可以让大数更快跳转到后面去而不是一次一次往后移动。_2,代码实现//希尔排序2--每组并着排 void ShellSort2(int* a, int n) { int gap n; while (gap 1) { //1保证最后一个gap为1 gap gap / 3 1; //每组并着排序 for (int i 0; i n - gap; i) { int end i; int tmp a[end gap]; //进行后移 while (end 0 tmp a[end]) //注意防止越界访问 { a[end gap] a[end]; end - gap; } //后移完进行插入 a[end gap] tmp; } } }另一种写法//希尔排序2--每组并着排 void ShellSort2(int* a, int n) { int gap n; while (gap 1) { gap gap / 3 1; //每组并着排序 for (int i 0; i n - gap; i) { int end i; int tmp a[end gap]; //进行后移 while (end 0 tmp a[end]) //注意防止越界访问 { a[end gap] a[end]; end - gap; } //后移完进行插入 a[end gap] tmp; } } }_3,总结当gap1时都是预排序让数组更接近有序。当gap1时数组已经非常接近有序此时进行插入排序就会非常快。希尔排序的时间复杂度为O(N^1.3)由于没有额外开辟数组空间所以空间复杂度为O(1)3选择排序Select sort_1,核心思想每次从待排序列中选出最大值和最小值放在序列的两端直到待排序列中的元素个数为零。遍历数组找到并存储最大值和最小值和选定序列的开头结尾元素进行交换。_2,代码实现//交换元素值 void Swap(int* a, int* b) { int tmp *a; *a *b; *b tmp; } //选择排序 void SelectSort(int* a, int n) { int begin 0; int end n - 1; while (begin end) { //假设最大值和最小值均为begin int mini begin, maxi begin; //找出最大值和最小值--从begin的下一个位置进行遍历 for (int i begin 1; i end; i) { if (a[i] a[mini]) { mini i; } if (a[i] a[maxi]) { maxi i; } } //进行元素的交换 Swap(a[mini], a[begin]); //排除特殊情况 if (maxi begin) { maxi mini; } Swap(a[maxi], a[end]); begin; end--; } }特殊情况分析_3,总结时间复杂度最坏情况n-1n-3n-5……1 n^2 / 4所以时间复杂度为:O(N^2)没有额外创建新空间空间复杂度为O(1)4堆排序Heap sort堆排序是基于数据结构堆的一种高效的排序方法。堆排序可以分为两步1建队 2排序下面给一个例子给定一个数组 a {8,9,7,2,5,4,1,6}要求将数组按照从小到大的顺序进行排序第一步建小堆方法一向上调整建小堆向上调整只需要上方的树都是小堆即可将数组中的元素从左到右进行向上调整也就是从树的根节点开始进行调整这样可以保证每要调整一个节点时该节点上面的节点都有序。分析时间复杂度方法二向下调整建小堆先找到倒数第一个分支节点进行向下调整再不断向前找元素进行调整直到遍历到根节点。分析时间复杂度第二步排序时间复杂度分析代码实现//堆排序 void heapsort(int* a,int n) { //升序建大堆 //降序建小堆 //降序-向上调整算法建小堆 //for (int i 1; i n; i) //{ // AdjustUp(a, i); //} //降序-向下调整算法建小堆 for (int i (n - 1 - 1) / 2; i 0; i--) { Adjustdown(a, n, i); } int end n - 1; while (end 0) { HPswap(a[0], a[end]); Adjustdown(a, end, 0); end--; } } void HPhead2() { int ar[] { 5,6,8,3,2,7,1,4,9 }; int sz sizeof(ar) / sizeof(ar[0]); heapsort(ar, sz); } int main() { //HPtest(); HPhead2(); return 0; }按照向下调整建小堆总体的时间复杂度为N^2*logN按照向上调整建小堆总体的时间复杂度为N^2*(logN)^2空间复杂度没有额外开辟空间故为O(1)5冒泡排序(Bubble sort)_1,核心思想:对相邻两个元素进行比较,然后进行排序。分析对一个数组内的元素进行排序例如数组内元素为 10 9 8 7 6 5 4 3 2 1按照升序的方式排列1 2 3 4 5 6 7 8 9 10我们需要先选取10和9两个元素进行比较在交换两个元素的位置依次往下进行当遍历完数组内所有元素后变为9 8 7 6 5 4 3 2 1 10。接着我们需要重复上述过程总共进行遍历9次得到升序数组。_2,代码实现_3,总结冒泡排序的时间复杂度为最坏情况倒序n-1n-2n-3……1 n*(n-1) / 2故最终为O(N^2)冒泡排序空间复杂度没有额外开辟空间故为O(1)6快速排序Quick sort_1,核心思想在数组中选取一个数作为基准值通过这个基准值将数组分成两个子数组让左子数组的值均小于基准值右子数组的值均大于基准值然后将左右数组的中间值和基准值进行交换 使得基准值左边的元素都比它小右边的都比他大然后再对左右数组进行递归快速排序。步骤通常选取数组最左边或者最右边的数当作基准值然后定义两个下标一个从左边开始向右走一个从最右边开始向左走。当检查到左数组中有比基准值还要大的值时停止当检查到右数组中有比基准值还要小的值时停止然后将两个值进行交换。相遇时停止停止位置的值一定小于key原因后面有解释并把key的值放到相遇的位置。递归部分然后以keyi为基准对数组进行分割分割为左数组部分和右数组部分。再对左右数组分别进行快速排序递归直到递归到左右数组中只有一个元素时终止此时进行返回最后得到的数组就是有序的。_2,代码实现//交换元素 void Swap(int* a, int* b) { int tmp *a; *a *b; *b tmp; } //快速排序 void QuickSort(int* a, int left,int right) { //当小区间只剩下一个数时跳出终止 if (left right) return; int begin left; int end right; int keyi left; //查找并交换元素 while (begin end) { //先从右找小 while (begin end a[end] a[keyi])//防止end--后不满足条件 { end--; } //再从左找大 while (begin end a[begin] a[keyi])//防止begin后不满足条件 { begin; } //进行交换 Swap(a[end],a[begin]); } //此时begin和end已经相遇要和keyi进行交换 Swap(a[keyi], a[begin]); keyi begin; //对数组进行分割然后进行对左右子数组递归 //[left,keyi-1] keyi [keyi1,right] QuickSort(a, left, keyi - 1); QuickSort(a, keyi1, right); }_3,时间和空间效率快速排序的时间复杂度快速排序的高度类似二叉树的高度高度为logNN/2^h 1 N 2^h h logN每一层都相当于遍历了整个数组共N次所以最后快速排序的时间复杂度就为: O(N*logN)空间复杂度空间复杂度不仅包含手动管理的“显式数组”还包含程序运行所包含的“隐式内存”主要是函数调用栈开辟栈帧空间。由于同一个栈帧空间可以在上次调用完函数被销毁后再次作为下一个函数相同但参数不同的函数进行调用时再次创建这个栈帧空间其实际上进行排序时最多存在的栈帧空间为递归树的最大深度logN。所以说空间复杂度实际是同时存活的栈帧空间个数而不是总共开辟了多少次栈帧空间。综上空间复杂度为logN下面是时间和空间复杂度的最坏情况:最坏情况下时间复杂度可以退化为:O(N^2)空间复杂度可以退化为O(N)由于向下递归的次数较多递归深度较深而每次递归都会调用函数开辟栈帧空间所以可能会造成栈溢出。_4,优化方法三数取中法和小区间优化具体思路取数组中最左边的数和最右边的数以及最中间的数。进行比较选取值的大小排中间的数并把它放到数组的最左边。代码展示//取中间值 int GetMidi(int* a, int left, int right) { int mid (left right) / 2; if (a[left] a[mid]) { if (a[mid] a[right]) { return a[mid]; } else if (a[left] a[right]) { return a[right]; } else { return a[left]; } } else //a[left] a[mid] { if (a[right] a[mid]) { return a[mid]; } else if (a[left] a[right]) { return a[left]; } else { return a[right]; } } }优化2,小区间优化当数组被分为比较小的时候可以不使用快速排序的递归可以直接使用其他的排序算法对小数组进行排序。防止递归的次数太多影响效率。由于经过前面的几次快速排序数组接近有序可以直接使用插入排序。最终优化后代码//快速排序 void QuickSort(int* a, int left,int right) { //当小区间只剩下一个数时跳出终止 if (left right) return; //小区间优化 if ((right - left 1) 10) //right-left1 为数组中值的个数 { Insertsort(aleft, right-left1); } else { //三数取中 int midi GetMidi(a, left, right); Swap(a[midi], a[left]); int begin left; int end right; int keyi left; //查找并交换元素 while (begin end) { //先从右找小 while (begin end a[end] a[keyi])//防止end--后不满足条件 { end--; } //再从左找大 while (begin end a[begin] a[keyi])//防止begin后不满足条件 { begin; } //进行交换 Swap(a[end], a[begin]); } //此时begin和end已经相遇要和keyi进行交换 Swap(a[keyi], a[begin]); keyi begin; //对数组进行分割然后进行对左右子数组递归 //[left,keyi-1] keyi [keyi1,right] QuickSort(a, left, keyi - 1); QuickSort(a, keyi 1, right); } }补充解释为什么left和right相遇的位置的数一定比key小_5,先后指针法实现单趟排序核心思路代码实现//单趟排序--前后指针法 int PartSort2(int* a, int left, int right) { //三数取中 int midi GetMidi(a, left, right); Swap(a[midi], a[left]); //创建指针变量 int key left; int prev left; int cur prev 1; while (cur right) { //小于就进行交换如果相等就不交换提升效率 if (a[cur] a[key] prev ! cur) //先prev后交换 { Swap(a[cur], a[prev]); } cur; } //跳出循环--进行交换 Swap(a[prev], a[key]); return prev; }_6,非递归实现快速排序本质分析这里通过栈来实现主要通过栈后进先出的特点来实现对规定区间的排序排序还是在原来的区间上进行排序代码实现//快速排序--非递归实现--利用栈 void QuickSortNone(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); //进行单次排序并找到key,进行分割 int key PartSort2(a, begin, end); //[begin,key-1] key [key1,end] //放入子序列为下次排序做准备--先放右边再放左边 if(key1 end) //区间中至少有两个元素 { STPush(st, end); STPush(st, key1); } if (begin key - 1) { STPush(st, key - 1); STPush(st, begin); } } }非递归实现快速排序的时间复杂度是O(N*logN)空间复杂度为O(logN)接下来我们考虑第一次调用到最深层次的节点时此时栈开辟的空间一定为最大值。计算这个最大值就是要计算的空间复杂度。由于整个过程相当于深度优先遍历当我们处理到这个区间时这个区间的兄弟区间还在栈中 其父亲区间一定已经出栈了其父亲区间的兄弟区间一定还在栈中再向上推导的父亲区间的兄弟区间还在栈中所以说除去第一层和最后一层每一层都有一个节点在栈中而第一层的一定不在栈中最后一层多一个在栈中所以总体来说就是高度logN7归并排序 Merge sort_1,核心思想归并排序的本质上是采用分治的思想先将原序列进行拆分 拆分为两个子数组在向下进行拆分直到拆分到数组中只有一个元素再把有序的子数组进行合并成一个新的有序数组直到合并成一个有序的数组。注意_2,代码实现//归并排序子函数--递归实现 void _MergeSort(int* a, int* tmp, int begin, int end) { //当区间只有一个数或区间不存在就返回 if (begin end) return; //先分割 int mid (begin end) / 2; //[begin,mid] [mid1,end] _MergeSort(a, tmp, begin, mid); _MergeSort(a, tmp, mid1, end); //进行合并 int begin1 begin, end1 mid; int begin2 mid1, end2 end; int i begin; //i的初始位置为begin //找小并尾插到新的数组当中 while (begin1 end1 begin2 end2) { if (a[begin1] a[begin2]) { tmp[i] a[begin1]; } else { tmp[i] a[begin2]; } } //将非空数组的其他数插入到tmp当中 while (begin1 end1) { tmp[i] a[begin1]; } while (begin2 end2) { tmp[i] a[begin2]; } //每次拷贝回去方便下一次进行比较 memcpy(a begin, tmp begin, (end - begin 1)*sizeof(int)); } //归并排序--递归实现 void MergeSort(int* a, int n) { int* tmp (int*)malloc(sizeof(int) * n); if (tmp NULL) { perror(malloc fail); return; } _MergeSort(a, tmp, 0, n - 1); free(tmp); tmp NULL; }_3,时间和空间效率时间复杂度合并时每一层中的每一个数都要进行比较总共有高度 logN层所以时间复杂度为ON*logN空间复杂度额外开辟一个大小为n的数组所以 空间复杂度为O(N)_4,非递归实现归并排序补充修正代码实现//归并排序--非递归实现 void MergeSortNonR(int* a, int n) { int* tmp (int*)malloc(sizeof(int) * n); if (tmp NULL) { perror(malloc fail); return; } //gap为每组中的数据个数 int gap 1; while (gap n) { //每一层的排序 for (int i 0; i n; i 2*gap) { int begin1 i, end1 i gap - 1; int begin2 i gap, end2 i 2 * gap - 1; //第二组都越界由于第一组已经有序直接跳出停止归并 if (begin2 n - 1) { break; } //只有end2越界进行修正,继续归并 if (end2 n - 1) { end2 n - 1; } //进行合并 int j i; //找小并尾插到新的数组当中 while (begin1 end1 begin2 end2) { if (a[begin1] a[begin2]) { tmp[j] a[begin1]; } else { tmp[j] a[begin2]; } } //将非空数组的其他数插入到tmp当中 while (begin1 end1) { tmp[j] a[begin1]; } while (begin2 end2) { tmp[j] a[begin2]; } //每次拷贝回去方便下一次进行比较 memcpy(a i, tmp i, (end2 - i 1) * sizeof(int)); } gap * 2; } free(tmp); tmp NULL; }8,计数排序Counting sort_1,核心思想计数排序是一种非比较型的线性时间排序算法适用于在一定范围内的整数。通过统计元素的出现次数直接确定元素在排列后在数组空间中的位置不依赖元素的比较。_2,代码实现//计数排序 void CountSort(int* a, int n) { //找a数组的范围range int min a[0], max a[0]; int i 0; for(i0;in;i) { if (min a[i]) { min a[i]; } if (max a[i]) { max a[i]; } } int range (max - min 1); //创建数组count--使用calloc表示创建并初始化为0 int* count (int*)calloc(range,sizeof(int)); if (count NULL) { perror(calloc fail); return; } //将每个数据的出现次数记录到count数组当中 for (int i 0; i n; i) { count[a[i] - min]; } //进行排序 int j 0; for (i 0; i range; i) { while (count[i]--) { a[j] i min; } } free(count); }_3,时间和空间效率时间复杂度为前面循环N次后面循环range次所以最后为O(Nrange)空间复杂度:由于额外创建了一个大小为range的数组所以空间复杂度为O(range )该方法只适用于数组中的数据都是整数并且整数比较集中。三各种排序总结及稳定性各种排序的比较稳定性当待排序数组中有两个及以上相同的数据元素排序前后这几个相同元素的相对位置没有发生变化。简单来说排序后有相同元素的相对位置发生改变就表明该排序不稳定。排序后相同元素的相对位置没有发生改变就表明该排序稳定。直接插入排序由于插入元素前面的元素已经有序当要插入的元素和前面的某元素相等时插入的元素也只会插入到前面的那个元素的后面一个位置相对位置不会发生改变所以比较稳定。希尔排序由于在进行预排序时要进行分组当有两个相同元素在不同的组时在进行预排序时对每组元素的排序就有可能造成相对位置的改变所以不稳定。选择排序由于下面的情况所以不稳定。堆排序冒泡排序前面的元素和后面的元素进行比较如果相等不进行交换所以相对位置不会发生改变比较稳定。快速排序由于下面的情况所以不稳定归并排序是按照原来的位置进行拆分拆分不会导致相对位置的改变拆分后进行合并时每个元素都要和其他元素进行比较即使相同元素也是先排左区间的元素后排右区间的元素相对位置不会发生改变所以稳定。

相关文章:

【数据结构】与排序算法鏖战5天,我终于搞懂了排序的思路和实现--排序算法大全的保姆级攻略

目录 一,排序的概念及分类 二,排序算法的实现 1,插入排序(intsert sort) _1,核心思路: _2,代码实现: _3,总结: 2,希尔排序(Shell sort) _…...

Weaviate向量数据库实战:从官方示例到RAG应用开发全解析

1. 项目概述:从代码仓库到向量数据库的实战指南如果你最近在关注大语言模型应用开发,或者想给自己的应用加上一个“记忆大脑”,那你大概率已经听说过向量数据库了。在众多选型中,Weaviate以其开源、易用和强大的功能脱颖而出。但当…...

【C++笔记】-- 七种排序流食般讲解

1.排序的概念:所谓的排序就是对于一组记录,按照某个或者某些关键字,递增或递减的排序这些记录。2.排序的分类:此文章将会介绍四类排序。一、插入排序:直接插入排序、希尔排序。二、选择排序:选择排序、堆排…...

MCP TypeScript SDK 服务说明文档

1. 服务概述 一句话简介:完整的MCP规范TypeScript实现,轻松构建MCP客户端和服务器,为LLM应用提供标准化的上下文管理能力。 服务名称:MCP TypeScript SDK版本号:Latest开发者/提供方:federated-alpha协议…...

ARM CP15寄存器详解与底层开发实践

1. ARM CP15寄存器概述CP15是ARM架构中的系统控制协处理器,负责管理处理器核心的关键功能模块。作为嵌入式系统开发人员,理解CP15寄存器的工作原理和操作方法,是进行底层系统软件开发的基础。CP15寄存器通过协处理器指令MRC(读)和MCR(写)进行…...

可配置处理器技术:嵌入式SOC设计的灵活加速方案

1. 可配置处理器技术概述在嵌入式系统芯片(SOC)设计领域,算法实现方式的选择一直是个关键决策点。传统上,开发者面临两种主要选择:要么将算法编译成通用处理器(如RISC或DSP)可执行的软件,要么将其直接实现为专用硬件电路(ASIC)。前…...

通过 Taotoken 的 Token Plan 套餐在 Ubuntu 长期项目中实现预算可控

🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 通过 Taotoken 的 Token Plan 套餐在 Ubuntu 长期项目中实现预算可控 在长期运行的 AI 辅助项目中,成本的可预测性和可…...

OpenClaw入门教程(1)——CLI 与 UI 配置详解

# OpenClaw 核心概念详解(一):CLI 与 UI 配置 创建日期:2026-04-21 | 作者:AiToMoney团队 🐉 | 版本:v1.0 | 适用版本:OpenClaw 2026.4.14+ 📖 概述 OpenClaw 4.14 版本提供了两种配置方式:CLI(命令行) 和 UI(图形界面),相比 3.13 版本的手动编辑 JSON 文件…...

8.4.3 开始屏幕和任务栏的优化:StartAllBack 找回高效 Windows 11 使用体验

🔥 个人主页: 杨利杰YJlio ❄️ 个人专栏: 《Sysinternals实战教程》 《Windows PowerShell 实战》 《WINDOWS教程》 《IOS教程》 《微信助手》 《锤子助手》 《Python》 《Kali Linux》 《那些年未解决的Windows疑难杂症》 🌟 让…...

大语言模型评测框架解析:从公平对比到工程选型实践

1. 项目概述与核心价值最近在GitHub上看到一个挺有意思的项目,叫“ai-llm-comparison”。光看名字,你大概能猜到它是做什么的——对比不同的大语言模型。但如果你以为这只是个简单的跑分列表,那就太小看它了。作为一个在AI应用开发领域摸爬滚…...

AI重构职场,30岁已成人生分水岭:程序员的两种人生与一种新活法

AI重构职场,30岁已成人生分水岭:程序员的两种人生与一种新活法在AI写下50%代码的2026年,30岁不再只是年龄数字,而是划分两种职业生涯、两种生活状态的分界线。2026年3月的一个周五晚上,29岁的杭州后端工程师李明&#…...

AI编码助手经验治理:ExperienceEngine解决重复错误与智能进化

1. 项目概述:为编码智能体引入“经验治理层”如果你和我一样,长期使用像 Claude Code、Cursor 或 OpenClaw 这类 AI 编码助手,肯定会遇到一个让人头疼的问题:同一个项目里,AI 助手会反复犯下几乎一模一样的错误。比如&…...

【C++ -Day7】封装实战 | 用类封装日志、配置和文件操作模块

引言 封装是面向对象三大特性(封装、继承、多态)中最基础也最重要的一环。在嵌入式开发中,代码的安全性、可维护性和可复用性直接决定了项目的成败。通过封装,我们可以将数据和操作隐藏在类内部,只暴露简洁的接口&…...

【C#】 HTTP 请求通讯实现指南

在现代软件开发中,HTTP 协议是应用程序与外部服务交互的核心桥梁。C# 作为 .NET 生态的主力语言,提供了丰富而成熟的 HTTP 通讯能力。本文将系统介绍 C# 中实现 HTTP 请求的技术选型、核心概念、常见场景及最佳实践,帮助开发者构建稳定、高效…...

Spring 第四天:AOP 面向切面编程与声明式事务管理

前言 Spring 有两大核心:一个是前几天我们重点攻克的 IoC/DI,另一个就是今天要深入学习的 AOP(面向切面编程)。 还记得那句话吗?“AOP 是在不改变原有代码的前提下对其进行功能增强”。听起来很神奇对吧?今…...

Groundhog:基于Git仓库的开发者时间自动追踪工具

1. 项目概述:一个面向开发者的时间管理利器如果你是一名开发者,或者你的工作与代码、项目、任务紧密相关,那么你一定对“时间都去哪儿了”这个问题深有感触。我们每天在各种编辑器、终端、浏览器标签页之间切换,处理着功能开发、B…...

CTO 每月烧 600 亿 token,3 个月完成百名程序员七八年写的 800 万行代码

①2026 年 5 月 9 日,昆仑万维董事长方汉的一番发言引热议,相关话题冲上热搜。方汉近日在访谈中坦承,自己每月实际消耗的 Token 高达 20 亿至 30 亿。此前他对外宣称的数字仅为 1 亿,属于刻意的低调处理。他甚至略带自嘲地表示&am…...

12,Springboot3+vue3实现系统公告功能

做一个新的公告模块步骤如下 一, 后端 1, 创建系统公告表 CREATE TABLE `notice` (`id` int NOT NULL AUTO_INCREMENT COMMENT 主键ID,`title` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 公告标题,`content` varchar(255) COLLATE utf8mb4_unicode_ci …...

从DES到AES:被‘遗忘’的IDEA算法,它的设计思想给现代密码学留下了什么?

从DES到AES:被遗忘的IDEA算法如何塑造现代密码学 1991年诞生的IDEA算法曾被誉为"DES的完美继任者",却在历史舞台上悄然退场。当我们在讨论AES和椭圆曲线加密时,很少有人记得这个瑞士学者设计的算法如何影响了整个加密技术发展轨迹。…...

高精度电压基准技术:LT6657的创新与应用

1. 高精度电压基准的技术演进与系统需求在精密数据采集系统的设计中,电压基准如同整个系统的"心脏",其稳定性直接决定了测量结果的可靠性。过去二十年里,我参与过数十个工业测量项目,深刻体会到基准源选择对系统性能的致…...

别再傻傻切片了!PyTorch Tensor高级索引实战:用index_select、masked_select和gather提升数据处理效率

别再傻傻切片了!PyTorch Tensor高级索引实战:用index_select、masked_select和gather提升数据处理效率 在深度学习项目的日常开发中,数据处理环节往往占据了开发者大量的时间和精力。许多PyTorch用户习惯性地使用基础切片操作来处理Tensor数据…...

视频技术演进:从模拟到数字的革命与压缩技术解析

1. 视频技术演进:从模拟到数字的革命上世纪30年代末,当第一套视频标准在美国诞生时,谁也没想到这个被称为RS-170的技术会成为现代视频技术的基石。作为最早的模拟视频标准,RS-170定义了525线(其中480线为有效视频内容&…...

别再只用Matplotlib画图了!用Python这3个库(SciPy, NumPy, Scikit-learn)给你的数据曲线做个‘美容’

Python数据平滑三剑客:用Savitzky-Golay、插值与滑动平均打造专业级图表 当你面对满是噪点的折线图时,是否想过这些锯齿状的波动正在掩盖数据的真实故事?就像摄影师不会直接发布未经修饰的RAW格式照片,数据科学家也需要掌握图表美…...

第五篇:Spring事务管理——@Transactional的底层实现与失效场景

前言 在前面的文章中,我们拆解了Spring AOP的底层原理——动态代理和切面编程。现在,我们来看AOP最经典的应用:事务管理。 你每天用着Transactional,往Service方法上一加,事务就自动开启了。但面试中,事务是…...

AI代理协作平台agtx:用终端看板管理多AI编程工作流

1. 项目概述:一个能管理其他AI编程代理的终端看板如果你和我一样,每天要在Claude、Cursor、Codex这些AI编程工具之间来回切换,同时处理多个功能需求,那你肯定也经历过这种混乱:一个终端窗口里,Claude正在写…...

SQL与数据库开发(四):CASE WHEN 与“行转列/列转行”花式玩法

在企业级应用的开发中,后端程序员和报表工程师往往面临着一种天然的矛盾:“数据库的存储格式”与“前端的展示格式”是完全不匹配的。 关系型数据库最喜欢“瘦长”的表(不断往下插入新行),而业务方和老板最喜欢看的是…...

Linux系统编程-makefile文件与make命令的使用

目录 一.makefile文件 1.1什么是makefile 1.2 makefile的一、二、三 1.2.1 一个规则 (1) 两个基本原则: (2) 使用 ALL 来指定makefile的终极目标: 1.2.2 两个函数 (1) src $(wildcard *.c) (2) obj $(patsubst %.c, %.o, $(src)) 1.2.3 三个…...

AI Agent集成Kalshi预测市场交易技能:自动化交易与风险管理实战

1. 项目概述:一个为AI Agent设计的Kalshi预测市场交易技能如果你对量化交易、自动化脚本或者新兴的AI Agent生态感兴趣,并且听说过“预测市场”这个概念,那么今天聊的这个项目可能会让你眼前一亮。lacymorrow/openclaw-kalshi-trading-skill本…...

AI伦理编程实战:从公平性算法到可解释性模型的工程实践

1. 项目概述:当代码开始思考,我们该教它什么? “AI伦理编程”这个词,听起来像是一个技术乌托邦,一个我们只要遵循几条规则就能让机器变得善良的简单任务。但当你真正坐下来,试图将“公平”、“透明”、“无…...

机器学习在非洲公共卫生疾病预测中的实战应用与技术解析

1. 项目概述:当AI遇见非洲公共卫生在非洲大陆,公共卫生系统长期面临着资源不均、基础设施薄弱和疾病负担沉重的多重挑战。传统的疾病监测依赖于被动报告和人工数据分析,往往存在滞后性,当疫情警报拉响时,病毒可能已经悄…...