10. 七大排序(含四种版本快排及优化) ******
排序算法 | 时间复杂度(平均) | 时间复杂度(最坏) | 时间复杂度(最好) | 空间复杂度 | 稳定性 | 主要使用场景 |
---|---|---|---|---|---|---|
直接插入排序 | O(n²) | O(n²) | O(n) | O(1) | 稳定 | 小规模数据或基本有序数据 |
希尔排序 | O(n^1.3) | O(n²) | O(n log n) | O(1) | 不稳定 | 中等规模数据,对稳定性无要求 |
选择排序 | O(n²) | O(n²) | O(n²) | O(1) | 不稳定 | 小规模数据,交换次数最少 |
堆排序 | O(n log n) | O(n log n) | O(n log n) | O(1) | 不稳定 | 大规模数据,需要原地排序 |
冒泡排序 | O(n²) | O(n²) | O(n) | O(1) | 稳定 | 小规模数据 |
快速排序 | O(n log n) | O(n²) | O(n log n) | O(log n) | 不稳定 | 大规模数据,通用排序 |
归并排序 | O(n log n) | O(n log n) | O(n log n) | O(n) | 稳定 | 大规模数据,需要稳定排序 |
目录
1. 插入排序
1.1 直接插入排序
1.2 希尔排序
2. 选择排序
2.1 选择排序
2.2 堆排序
3. 交换排序
3.1 冒泡排序
3.2 快速排序
1.霍尔版本:
2.挖坑法:
3. 前后指针法(推荐)
4. 快排非递归(掌握)
3.3 快速排序的优化方法
1. 三数取中法选key
2.递归到小的子区间时,可以考虑使用插入排序
4.归并排序
1. 插入排序
1.1 直接插入排序
当插入第 i 个元素时,前面的[0, i-1] 已经排好序了,此时用 arr[i] 和 arr[i-1]、arr[i-2]......依次比较,将原来位置上的元素后移,直到找到插入位置,将元素插入。
912. 排序数组
class Solution
{
public:vector<int> sortArray(vector<int>& nums) {int n = nums.size();for(int i=1; i<n; i++){int j = i-1;int tmp = nums[i];while(j >= 0 && tmp < nums[j]) //如果要排序的值小于前面某位置的值{nums[j+1] = nums[j];//前面的值向后一个位置移j--;//继续向前找}nums[j+1] = tmp;//当要排序的值大于等于j位置的值,就可以放到j后面的一个位置}return nums;}
};
1.2 希尔排序
希尔排序的基本思想是:先选定一个gap,将待排序的数据按gap分组,对每组进行排序,当取gap=1时,数组接近有序,使用插入排序就会很快。
class Solution
{
public:vector<int> sortArray(vector<int>& nums) {int n = nums.size();for(int gap=n/2; gap>0; gap/=2){for(int i=gap; i<n; i++){int j = i-gap;int x = nums[i];while(j >= 0 && x < nums[j]){nums[j+gap] = nums[j];//nums[j]的值后放到 j+gapj -= gap;}nums[j+gap] = x;}}return nums;}
};
我们可以发现和插入排序的代码差不多,希尔排序是对直接插入排序的优化。
当 gap>1时都是预排序,目的是让数组更接近于有序。当gap = 1时,数组接近有序,在进行直接插入排序就会很快。达到优化的效果。
我们可以发现gap=1时,上面的代码就是直接插入排序的代码。
因为gap的取值方式很多,所以时间复杂度不好计算,我们记个O(N^1.3)就行。
2. 选择排序
2.1 选择排序
每次从待排序数据中选择最小(大)的那个,存放在序列的起始位置,直到全部待排序元素排完。
上图中红色的就是遍历数组中选出的当前的最小值,遍历结束后,和当时的排好序的下一个位置进行交换。
class Solution
{
public:vector<int> sortArray(vector<int>& nums) {int n = nums.size();for(int i=0; i<n-1; i++)//遍历准备交换的位置{int mini = i;for(int j=i+1; j<n; j++)//找min位置{if(nums[j] < nums[mini])mini = j;}if(mini != i)//如果最小位置不是i位置就交换,相等就没必要交换了swap(nums[mini], nums[i]);}return nums;}
};
实际中很少使用,好理解但是效率不高。
2.2 堆排序
排升序-建大堆:大的数在堆顶,和最后比较小的数据交换,然后把堆顶这个小的数据向下调整,大的就放到了数组最后,最后排出来就是升序的数组。
排降序-建小堆:同理,小的在堆顶,小的一直和大的换,小的就被放到了数组最后。
上图就是从建堆-向上调整建立大堆-大堆排升序。
7. 二叉树****-CSDN博客 中有关于堆的详细介绍和实现。
class Solution
{
public:vector<int> sortArray(vector<int>& nums) {//建大堆int n = nums.size();for(int i=(n-1)-1/2; i>=0; i--)//从i这个位置开始向前调整,可以确保每次调整时,子树已经是堆结构{adjustdown(nums, i, n);//向下调整需要子树都是堆}//堆排for(int i=n-1; i>0; i--){swap(nums[i], nums[0]);adjustdown(nums, 0, i);}return nums;}void adjustdown(vector<int>& nums, int parent, int sz){int child = parent*2+1;while(child < sz){if(child+1 < sz && nums[child+1] > nums[child])child++;if(nums[child] > nums[parent]){swap(nums[child], nums[parent]);parent = child;child = parent*2+1;}elsebreak;}}
};
3. 交换排序
根据两个值的比较结果来对换两个值在序列中的位置,将大的向尾部移动,值小的向前移动。
3.1 冒泡排序
class Solution
{
public:vector<int> sortArray(vector<int>& nums) {int n = nums.size();for(int i=0; i<n-1; i++){bool exchange = false;for(int j=0; j<n-i-1; j++)//每一趟都把最大的放到最后,所以要-i,i=1时说明最后一个位置放好了{if(nums[j] > nums[j+1]){swap(nums[j], nums[j+1]);exchange = true;}}if(exchange = false)//如果某轮没有交换过,说明已经排序好了,程序可以结束了break;}return nums;}
};
3.2 快速排序
任取待排序元素序列中的某元素作为基准值,按照该元素将待排序列分割成两子序列,左子序列中所有元素均小于基准值,右子序列中所有元素均大于基准值,重复该过程,直到所有元素排好。
将区间按照基准值划分为左右两部分的常见方式有三种:
1.霍尔版本:
我们需要一左一右两个指针,left 指向6, right 指向8,最左边 6 做 keyi。
如果 left < right:
right一定要先走(才能保证相遇时一定比k小),right 从右向左找比 k 小的,找到一个5,停下;
left 从左向右找比 k 大的,找到一个7,停下;
交换5和7
left < right,然后重复上面的过程,right先走找到4,left后走找到9,交换:
继续重复,right先走找比k小,找到3,left后走找比k大,没找到,与right相遇了:
然后交换 nums[keyi] 和 nums[left],当前这个keyi的位置就排好了。
然后去 keyi 的左边和右边的区间分别走同样的快排。
class Solution
{
public:vector<int> sortArray(vector<int>& nums) {int n = nums.size();QuickSort1(nums, 0, n-1);return nums;}void QuickSort1(vector<int>& nums, int left, int right){if(left >= right)return;int begin = left, end = right;//递归要用每更新的left和right找区间int keyi = left;while(left < right){while(left < right && nums[right] >= nums[keyi])right--;while(left < right && nums[left] <= nums[keyi])left++;swap(nums[left], nums[right]);}swap(nums[left], nums[keyi]);keyi = left;QuickSort1(nums, begin, keyi-1);QuickSort1(nums, keyi+1, end);}
};
2.挖坑法:
和第一种差不多,只不过多了一个“坑”的中间状态
选最左边为key,key为坑,先右左移找比k小,找到就放进坑里,right指向的为新坑;
左向右移找比k大,找到就放进坑里,left指向为新坑,
left < right,重复上述过程。直到left == right时,两者相遇在坑中,坑里填最开始选的key。
class Solution
{
public:vector<int> sortArray(vector<int>& nums) {int n = nums.size();QuickSort2(nums, 0, n-1);return nums;}void QuickSort2(vector<int>& nums, int left, int right){if(left >= right)return;int begin = left, end = right;//递归要用每更新的left和right找区间int key = nums[left];int hole = left;while(left < right){while(left < right && nums[right] >= key)right--;nums[hole] = nums[right];hole = right;while(left < right && nums[left] <= key)left++;nums[hole] = nums[left];hole = left;}nums[hole] = key;QuickSort2(nums, begin, hole-1);QuickSort2(nums, hole+1, end);}
};
3. 前后指针法(推荐)
初始时,prev指向数组开头,cur指向prev下个位置:
然后 cur 找到比 key 小的,++prev,cur 与 prev 交换:
但是如果++prev == cur,那就没必要交换了,交换了也一样,直接cur++
如果要交换,换完以后 cur++
此时cur又小于key,但是++prev == cur,cur++,cur指向7,大于key,cur++,直到指向3:
++prev != cur,交换他们的值:
换完以后cur++,指向4,小于key,++prev != cur,交换以后,cur++指向5
又小于key,++prev != cur,交换以后cur++
cur指向的一直大于key,一直++,直到大于right,此时交换prev指向的值和key。
完成一轮的排序,接下来还是去左区间和右区间排序,和前两种方法是一样的。
为什么可以这样直接换:
prev要么紧跟cur,要么紧跟大于key的数,既然它紧跟大于key的,说明它本身小于key,所以可以直接换。
class Solution
{
public:vector<int> sortArray(vector<int>& nums) {int n = nums.size();QuickSort3(nums, 0, n-1);return nums;}void QuickSort3(vector<int>& nums, int left, int right){if(left >= right)return;int begin = left, end = right;//递归要用每更新的left和right找区间int keyi = left;int prev = left, cur = prev+1;while(cur <= right){if(nums[cur] < nums[keyi] && ++prev != cur)swap(nums[cur], nums[prev]);cur++;}swap(nums[prev], nums[keyi]);keyi = prev;QuickSort3(nums, begin, keyi-1);QuickSort3(nums, keyi+1, end);}
};
4. 快排非递归(掌握)
递归的问题是如果深度太深会栈溢出。
class Solution
{
public:vector<int> sortArray(vector<int>& nums) {int n = nums.size();QuickSortNR(nums, 0, n-1);return nums;}//由快排前后指针改造来的单次排序分区函数int partSort3(vector<int>& nums, int left, int right){int keyi = left;int prev = left, cur = prev+1;while(cur <= right){if(nums[cur] < nums[keyi] && ++prev != cur)swap(nums[cur], nums[prev]);cur++;}swap(nums[prev], nums[keyi]);keyi = prev;return keyi;}void QuickSortNR(vector<int>& nums, int left, int right){stack<int> st;st.push(right);st.push(left);while(!st.empty()){int begin = st.top();st.pop();int end = st.top();st.pop();int keyi = partSort3(nums, begin, end);if(keyi + 1 < end){st.push(end);st.push(keyi+1);}if(begin+1 < keyi){st.push(keyi-1);st.push(begin);}}}
};
解释:
int keyi = partSort3(nums, begin, end);
根据当前的begin和end进行单趟排序的同时,得出一个新keyi,下面再根据这个新的keyi划分左右区间,入栈,栈不为空就取栈中前两个数做新的begin、end单趟排序。直到栈为空,说明所有区间都排过序了。
3.3 快速排序的优化方法
1. 三数取中法选key
优化方法 | 时间复杂度保证 | 额外开销 | 抗极端数据能力 | 实现复杂度 |
---|---|---|---|---|
随机选择 | 平均 O(nlogn) | 随机数生成 | 强 | 简单 |
三数取中 | 平均 O(nlogn) | 三次比较 | 更强 | 中等 |
大多数标准库(如 C++ std::sort
)采用三数取中,因为它在实际数据中表现更稳定,比纯随机选择更快(减少约 5%-10% 的比较次数)。
int GetMidNumi(vector<int>& nums, int left, int right)
{int mid = (left + right) / 2;if (nums[left] < nums[mid]){if (nums[mid] < nums[right]) //left mid rightreturn mid;else if (nums[left] > nums[right])return left; //right left mid elsereturn right; //left right mid}else // nums[left] > nums[mid]{if (nums[mid] > nums[right]) //right mid leftreturn mid;else if (nums[left] < nums[right])return left; //mid left rightelsereturn right; //mid right left}
}
上面注释中代表的是下标对应的值的大小顺序。很明显的看出返回中间那个。
2.递归到小的子区间时,可以考虑使用插入排序
进一步优化:
结合两者(三数取中 + 小规模数组改用插入排序)是更高级的优化策略。
int PartSort3(vector<int>& nums, int left, int right){int midi = GetMidNumi(nums, left, right);if(midi != left)swap(nums[midi], nums[left]);//最好中位数去做key值int keyi = left;int prev = left, cur = prev+1;while(cur <= right){if(nums[cur] < nums[keyi] && ++prev != cur)swap(nums[cur], nums[prev]);cur++;}swap(nums[prev], nums[keyi]);keyi = prev;return keyi;}void QuickSort(vector<int>& nums, int left, int right){if (left >= right)return;// 小区间优化--小区间直接使用插入排序if ((right - left + 1) > 10){int keyi = PartSort3(nums, left, right);QuickSort(nums, left, keyi - 1);QuickSort(nums, keyi + 1, right);}else{InsertSort(nums+left, right - left + 1);}}
小区间使用插入排序代替递归效率更高。
4.归并排序
归并是建立在归并操作上的一种有效的排序算法,该算法是采用分治法。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序数组合成一个有序数组,称为二路归并。
class Solution
{vector<int> tmp;
public:vector<int> sortArray(vector<int>& nums) {tmp.resize(nums.size());mergeSort(nums, 0, nums.size()-1);return nums;}void mergeSort(vector<int>& nums, int left, int right){//递归出口if(left >= right)return;//选择中间点划分int mid = (left+right)/2;//左右区间递归处理mergeSort(nums, left, mid);mergeSort(nums, mid+1, right);//合并两个有序数组int cur1 = left, cur2 = mid+1, i = 0;while(cur1 <= mid && cur2 <= right){tmp[i++] = nums[cur1] <= nums[cur2] ? nums[cur1++] : nums[cur2++];}//处理没有遍历完的数组while(cur1 <= mid) tmp[i++] = nums[cur1++];while(cur2 <= right) tmp[i++] = nums[cur2++];//还原到numsfor(int i=left; i<=right; i++){nums[i] = tmp[i-left];//tmp每次都是从0开始的,nums是从left开始的}}
};
大体过程分两步:
分:将数组一分为二两部分,一直分解到数组的长度为1,left == right,都指向这个数,return。使整个数组的排序过程被分为左半部分排序+右半部分排序。
治:将两个较短的有序数组合并成一个长的有序数组,一直合并到最初的长度。
比如5,2,3,1这个数组,一直分两部分最后就分成5,2两个长度为1的数组,他们各自的left == right,return,然后合并这两个数。合并完以后把tmp的内容放到nums中,此时一开始的merge(nums, 0, 1)结束了,该走merge(nums, 2, 3)也就是另一半了,同样的过程,最后把2,5和1,3合并到tmp中,用tmp更新nums。
相关文章:
10. 七大排序(含四种版本快排及优化) ******
排序算法时间复杂度(平均)时间复杂度(最坏)时间复杂度(最好)空间复杂度稳定性主要使用场景直接插入排序O(n)O(n)O(n)O(1)稳定小规模数据或基本有序数据希尔排序O(n^1.3)O(n)O(n log n)O(1)不稳定中等规模数据,对稳定性无要求选择排序O(n)O(n)O(n)O(1)不稳定小规模数…...
以下是C/C++后台开发常见的高概率面试题
一、语言基础 多态的实现 通过虚函数表(vtable)实现动态绑定,运行时根据对象类型调用对应的函数。虚函数通过virtual关键字声明,子类可重写基类虚函数112。 指针与引用的区别 指针是变量,存储地址,支持多…...
CentOS-查询实时报错日志-查询前1天业务报错gz压缩日志
最新版本更新 https://code.jiangjiesheng.cn/article/364?from=csdn 推荐 《高并发 & 微服务 & 性能调优实战案例100讲 源码下载》 1. 查询实时报错日志 物理路径(带*的放在靠后,或者不用*) cd /home/logs/java-gz-log-dir && tail -2000f java-gz-l…...
破界·共生:生成式人工智能(GAI)认证重构普通人的AI进化图谱
在当今这个科技日新月异的时代,人工智能(AI)正以惊人的速度改变着我们的世界。从智能家居到自动驾驶,从医疗诊断到金融分析,AI的应用已经渗透到社会生活的方方面面。面对如此迅猛的发展态势,我们不禁要问:人工智能的未来将走向何方?普通人又该如何把握这一历史机遇,学…...
HTTP代理:网页加速的隐形引擎
目录 引言:网页加载速度为何至关重要? 一、HTTP代理的核心加速原理 二、四大加速黑科技详解 三、实战场景性能对比 四、代理加速的隐藏代价 五、未来发展趋势 结语:智能代理的选型指南 引言:网页加载速度为何至关重要&#…...
Unity 常见报错 定位和查找方法
1.控制台 直接看报错信息 2.打log 例子: for(int i 0;i < 8;i) {Debug.Log(i);//这是打的log,看看到底i是几的时候出问题gameObject.name strs[i];} 3.断点调试 (1)在你想打断点的行,左边空白处点击可以打断点ÿ…...
人工智能之数学基础:初等反射阵
本文重点 在线性代数中,初等反射阵(Householder矩阵)作为一类特殊的正交矩阵,在矩阵变换、特征值计算及几何变换等领域具有广泛应用。其简洁的构造方式和丰富的数学性质,使其成为数值分析和几何处理中的重要工具。 什么是初等反射阵(豪斯霍尔德变换) I为单位矩阵,wwT…...
《Linux运维总结:基于银河麒麟V10操作系统+ARM64架构CPU二进制部署单机ACL版consul v1.18.1》
总结:整理不易,如果对你有帮助,可否点赞关注一下? 更多详细内容请参考:《Linux运维篇:Linux系统运维指南》 一、简介 1、什么是consul Consul是HashiCorp公司推出的开源工具,用于实现 分布式系统的服务发现与配置。 Consul是分布式的、高可用的、可横向扩展的。 架构图…...
web网站页面测试点---添加功能测试
添加 一、创建新的申请时,关闭网络查看数据是否存在,并提示网络错位相关提示语 二、在文本框内输入数据 1.在文本框内输入空格,查看文本内容前后是否存在空格 2.在文本框内输入最大长度,查看能否正确提交 3.在文本框内输入最大长…...
实操自动生成接口自动化测试用例
这期抽出来的问题是关于如何使用Eolinker自动生成接口自动化测试用例,也就是将API文档变更同步到测试用例,下面是流程的示例解析。 导入并关联API文档和自动化测试用例 首先是登陆Eolinker,可以直接在线使用。 进入流程测试用例详情页&am…...
【华为OD技术面试真题 - 技术面】- Java面试题(17)
华为OD面试真题精选 专栏:华为OD面试真题精选 目录: 2024华为OD面试手撕代码真题目录以及八股文真题目录 文章目录 华为OD面试真题精选虚拟机分区1. **虚拟磁盘分区**2. **虚拟机的内存分区**3. **CPU分配**4. **虚拟网络分区**5. **存储虚拟化和分区**6. **虚拟机分区管理**…...
mapState 函数的用法
mapState 是 Vuex 提供的一个辅助函数,其主要作用是将 Vuex 仓库中的状态映射到组件的计算属性中,这样在组件里就能像访问本地计算属性一样访问 Vuex 仓库中的状态。以下为你详细介绍 mapState 函数的不同用法。 1. 基本用法:对象形式 当使…...
【学Rust写CAD】17 通用2D仿射变换矩阵结构体(matrix/generic.rs)
源代码 // matrix.rs use std::ops::{Add, Mul};use std::ops::{Add, Mul};/// 通用2D仿射变换矩阵(元素仅需Copy) #[derive(Clone, Copy, Debug, PartialEq)] pub struct Matrix<X, Y, Xx, Xy, Yx, Yy> {pub x: X, pub y: Y,pub xx: Xx, pub xy:…...
STM32单片机入门学习——第3-4节: [2-1、2]软件安装和新建工程
写这个文章是用来学习的,记录一下我的学习过程。希望我能一直坚持下去,我只是一个小白,只是想好好学习,我知道这会很难,但我还是想去做! 本文写于:2025.04.01 STM32开发板学习——第一节: [1-1]课程简介 前言开发板说明引用解答和…...
Linux详解
01 计算机组成原理 1、什么是计算机? 计算机俗称电脑,就相当于一种人造人, 电脑二字蕴含着人类的对计算机的终极期望,希望一通电就能够像人脑一样去工作 2、为何要有计算机? 为了造出一种机器来取代人去工作&…...
IP数据报报文格式
一 概述 IP数据报由两部分组成:首部数据部分。首部的前一部分是固定长度,一共20字节大小,是所有IP数据报文必须具有的;固定部分后面是一些可选字段,其长度是可变的。 二 首部固定部分各字段意义 (1&…...
自然语言处理(25:(终章Attention 1.)Attention的结构)
系列文章目录 终章 1:Attention的结构 终章 2:带Attention的seq2seq的实现 终章 3:Attention的评价 终章 4:关于Attention的其他话题 终章 5:Attention的应用 目录 系列文章目录 前言 Attention的结构 一.seq…...
Minimind 训练一个自己专属语言模型
发现了一个宝藏项目, 宣传是完全从0开始,仅用3块钱成本 2小时!即可训练出仅为25.8M的超小语言模型MiniMind,最小版本体积是 GPT-3 的 17000,做到最普通的个人GPU也可快速训练 https://github.com/jingyaogong/minimi…...
Android里面内存优化
核心思路 在Android开发中,内存优化是保证应用性能稳定和用户体验的关键。我通常从以下几个方面进行内存优化: 1. 内存泄漏检测与修复 使用LeakCanary等工具检测内存泄漏 常见内存泄漏场景: 静态变量持有Activity/Fragment引用 非静态内部…...
Git操作指南
Git操作指南 1.安装并配置Git Git官网:https://git-scm.com/downloads 安装完成后,打开Git Bash,配置Git: git config --global user.email "emailexample.com" git config --global user.name "Your Name&quo…...
【蓝桥杯—单片机】通信总线专项 | 真题整理、解析与拓展 (更新ing...)
通信总线专项 前言SPI第十五届省赛题 UART/RS485/RS232UARTRS485RS232第十三届省赛题小结和拓展:传输方式的分类第十三届省赛 其他相关考点网络传输速率第十五届省赛题第十二届省赛题 前言 在本文中我会把 蓝桥杯单片机赛道 历年真题 中涉及到通信总线的题目整理出…...
深入探究C语言中的二进制世界:从原理到实践
文章目录 深入探究C语言中的二进制世界:从原理到实践一、进制的本质与C语言实现1. 进制系统全景2. C语言中的进制表示3. 格式化输出进阶 二、进制转换的工程实践1. 转换算法实现2. 实际应用中的转换技巧快速二进制 - 十六进制转换位运算优化转换 3. 进制转换详细示例…...
【android bluetooth 协议分析 13】【RFCOMM详解 2】【通俗易懂 rfcomm 基本流程】
RFCOMM 协议 基本流程 一、连接建立流程(附 BTsnoop 实例解析) 1. L2CAP 通道建立 BTsnoop 表现: L2CAP_Connection_Request (PSM0x0003) // 请求建立RFCOMM专用通道L2CAP_Connection_Response (Success) // 对方同意作用:相…...
万字知识篇(2):SpringBoot的常用注解(上)
SpringBoot的常用注解非常的多,一篇文章根本讲不完,将分为上下两章,通过本章你将会系统的学习到: 1. 注解在SpringBoot中的作用 2. SpringBoot 常用注解速查表 3. 核心启动类注解 4. Configuration 5. Bean 6. PropertySource 7. …...
Postman —— postman实现参数化
什么时候会用到参数化 比如:一个模块要用多组不同数据进行测试 验证业务的正确性 Login模块:正确的用户名,密码 成功;错误的用户名,正确的密码 失败 postman实现参数化 在实际的接口测试中,部分参数每…...
Docker学习--容器生命周期管理相关命令--docker create 命令
docker create 命令作用: 会根据指定的镜像和参数创建一个容器实例,但容器只会在创建时进行初始化,并不会执行任何进程。 语法: docker create[参数] IMAGE(要执行的镜像) [COMMAND](在容器内部…...
算法基础_基础算法【高精度 + 前缀和 + 差分 + 双指针】
算法基础_基础算法【高精度 前缀和 差分 双指针】 ---------------高精度---------------791.高精度加法题目介绍方法一:代码片段解释片段一: 解题思路分析 792. 高精度减法题目介绍方法一:代码片段解释片段一: 解题思路分析 7…...
C语言深度解析:从零到系统级开发的完整指南
一、C语言的核心特性与优势 1. 高效性与直接硬件控制 C语言通过编译为机器码的特性,成为系统级开发的首选语言。例如,Linux内核通过C语言直接操作内存和硬件寄存器,实现高效进程调度。 关键点: malloc/free直接管理内存&#…...
Axure疑难杂症:完美解决中继器筛选问题(时间条件筛选、任性筛选)
亲爱的小伙伴,在您浏览之前,烦请关注一下,在此深表感谢! 课程主题:中继器筛选专题 主要内容:时间条件筛选、多条件组合筛选、多个单一条件混合筛选 应用场景:各类数据表的多条件筛选均可使用…...
汇编学习之《扩展指令指针寄存器》
什么是指令指针寄存器? EIP (Extended Instruction Pointer): 保存cpu 下一次将要执行的代码的地址。 通过OllyGbd可以看到CPU即将执行指令的地址和EIP 内部放入的地址一致,多次F8依然是这样。 这里要区分下,之前比如EAX,ECX我…...
oracle-blob导出,在ob导入失败
导出: [oraclelncs dmp]$ /home/oracle/sqluldr2 gistar/res#pwd192.168.205.58:1521/lndb query"select * from an_odn_picture where length(PIC_CONTENT)<25000" filean_odn_picture.csv Charsetutf8 textCSV 0 rows exported at 2025-…...
【Linux笔记】进程间通信——匿名管道||进程池
🔥个人主页🔥:孤寂大仙V 🌈收录专栏🌈:Linux 🌹往期回顾🌹:【Linux笔记】动态库与静态库的理解与加载 🔖流水不争,争的是滔滔不 一、Linux进程间通…...
Spring Boot 3.4.3 基于 Caffeine 实现本地缓存
在现代企业级应用中,缓存是提升系统性能和响应速度的关键技术。通过减少数据库查询或复杂计算的频率,缓存可以显著优化用户体验。Spring Boot 3.4.3 提供了强大的缓存抽象支持,而 Caffeine 作为一款高性能的本地缓存库,因其优异的…...
windows使用nvm管理node版本
1.下载地址:https://github.com/coreybutler/nvm-windows/releases 选择nvm-setup.exe 2.安装,下载完成后,以管理员身份运行 nvm-setup.exe,选择默认安装,一路next 3.使用,安装完成后会打开一个命令行窗口࿰…...
vscode集成deepseek实现辅助编程(银河麒麟系统)【详细自用版】
针对开发者用户,可在Visual Studio Code中接入DeepSeek,实现辅助编程。 可参考我往期文章在银河麒麟系统环境下部署DeepSeek:基于银河麒麟桌面&&服务器操作系统的 DeepSeek本地化部署方法【详细自用版】 一、前期准备 (…...
智谱大模型(ChatGLM3)PyCharm的调试指南
前言 最近在看一本《ChatGLM3大模型本地化部署、应用开发和微调》,本文就是讨论ChatGLM3在本地的初步布设。(模型文件来自魔塔社区) 1、建立Pycharm工程 采用的Python版本为3.11 2、安装对应的包 2.1、安装modelscope包 pip install model…...
MySQL GROUP BY分组获取非聚合列值方法
在使用MySQL进行数据库查询时,如果你需要对数据按照某个或某些列进行分组(GROUP BY),并且希望在结果中包含非聚合列的值,你可以通过以下几种方法来实现: 1. 使用聚合函数 虽然这不是直接获取非聚合列值的…...
多路径 TCP 调度的另一面
参考前面的文章 一个原教旨的多路径 TCP 和 MP-BBR 公平性推演,一直都破而不立,不能光说怎样不好,还得说说现状情况下,该如何是好。 如果 receiver 乱序重排的能力有限(拜 TCP 所赐),如果非要在多路径上传输 TCP&…...
在Qt中判断输入的js脚本是否只包含函数
目前在使用QtScriptEngine,在利用evaluate注册子函数时,要求用户输入的js文件中的内容仅仅是函数,函数体外不能出现一些变量的声明、函数的调用等其他代码。 反复咨询DeepSeek后,终于给出了一个目前测试可用的代码: b…...
【Easylive】MySQL中LEFT JOIN与INNER JOIN的使用场景对比
【Easylive】项目常见问题解答(自用&持续更新中…) 汇总版 在MySQL数据库查询中,JOIN操作是最常用的操作之一,而LEFT JOIN和INNER JOIN是两种最基础的JOIN类型。理解它们的区别和适用场景对于编写高效、准确的SQL查询至关重要…...
Boost库中的谓词函数
Boost库中的谓词函数 谓词函数基础概念 在编程中,谓词函数(Predicate Function)是指返回布尔值(true或false)的函数,用于检测输入是否满足特定条件。谓词函数在STL算法和Boost库中被广泛使用,…...
人工智能之数学基础:基于初等反射矩阵完成矩阵的QR分解
本文重点 QR分解是矩阵分解中的一种重要方法,它将一个矩阵分解为一个正交矩阵Q和一个上三角矩阵R的乘积,即A=QR。这种分解在求解线性方程组、最小二乘问题、特征值计算等领域有着广泛应用。 QR分解的定义 QR分解就是应用了初等反射矩阵,不断的通过初等反射矩阵,然后将A变…...
AI应用案例(1)——智能工牌和会话质检
今天开辟一个新的模块,自己平时也搜集一些典型的行业应用案例,不如就记录到C站,同时和大家也是个分享好了。 今天分享的企业和产品,是循环智能的智能工牌。 这个产品应用场景清晰,针对的行业痛点合理,解决…...
碰一碰发视频系统--基于H5场景开发
碰一碰发视频#碰一碰发视频#开发基于H5的"碰一碰发视频"交互系统(类似华为/苹果的NFC碰传但通过移动端网页实现),需要结合近场通信(NFC/H5 API)和媒体传输技术。以下是具体实现方案 #碰一碰营销系统# #碰一…...
kotlin扩展函数的实现原理
1. 编译时转换 在编译时,Kotlin 扩展函数会被转换为静态函数。这个静态函数的第一个参数是接收者类型(也就是被扩展的类),而调用扩展函数时,实际上是调用这个静态函数,并将接收者对象作为第一个参数传入。…...
激活函数学习笔记
Sigmoid:梯度消失、指数计算复杂运行慢、输出不是以0为中心,梯度平滑便于求导tanh:以0为中心,其他与sigmoid相似ReLu:transformer常用,解决了梯度消失问题、计算复杂度低,存在神经元死亡问题和梯…...
【含文档+PPT+源码】基于Python爬虫二手房价格预测与可视化系统的设计与实现
项目介绍 本课程演示的是一款基于Python爬虫二手房价格预测与可视化系统,主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的 Java 学习者。 包含:项目源码、项目文档、数据库脚本、软件工具等所有资料 带你从零开始部署运行本套系统 该项…...
基于 Swoole 的高性能 RPC 解决方案
文章精选推荐 1 JetBrains Ai assistant 编程工具让你的工作效率翻倍 2 Extra Icons:JetBrains IDE的图标增强神器 3 IDEA插件推荐-SequenceDiagram,自动生成时序图 4 BashSupport Pro 这个ides插件主要是用来干嘛的 ? 5 IDEA必装的插件&…...
# 实时人脸识别系统:基于 OpenCV 和 Python 的实现
实时人脸识别系统:基于 OpenCV 和 Python 的实现 在当今数字化时代,人脸识别技术已经广泛应用于各种场景,从手机解锁到安防监控,再到智能门禁系统。今天,我将通过一个完整的代码示例,详细讲解如何使用 Pyt…...
python的global在编译层面的进阶理解
目录 报错情况 编译执行过程 (1)源代码(.py 文件) (2)编译阶段:解析 & 生成字节码 (3)解释执行:Python 虚拟机(PVM) 字节码…...