C++算法中的单调栈:从入门到实战指南

大家好!今天我们来聊聊C++算法中一个超级实用的工具——单调栈。别被名字吓到,它其实很简单,就像排队买奶茶一样:队伍总是从矮到高(或从高到矮)排得整整齐齐,这样处理问题时就特别高效。在算法面试里,单调栈是高频考点,LeetCode上很多难题(比如找“下一个更大元素”或算“柱状图最大面积”)都能用它轻松搞定。这篇文章,我会用接地气的语言,带大家一步步理解单调栈的原理、C++实现和应用。全程10000字以上,保证干货满满,读完你就能上手写代码!


一、引言:为什么单调栈这么牛?

想象一下,你在超市排队结账。如果队伍乱七八糟,收银员得花时间找谁先来谁后到,效率贼低。但如果队伍按身高排好(比如从矮到高),收银员一眼就能看出顺序,处理速度飞快。单调栈就是这个道理:它是个栈(后进先出的数据结构),但里面的元素保持单调递增或递减的顺序。这样处理数组问题时,能省下大量时间。

在C++算法中,单调栈为啥重要?首先,它能把时间复杂度从$O(n^2)$降到$O(n)$,空间复杂度也常是$O(n)$,这在处理大数据时救命啊!其次,接地气地说,它就像你的“算法瑞士军刀”——专治各种“找邻居元素”的毛病。比如:

  • 找数组中每个元素的下一个更大元素(Next Greater Element)。
  • 算柱状图中最大矩形面积(LeetCode经典题)。
  • 优化动态规划问题,避免重复计算。

别担心,我会用生活例子贯穿全文。比如,把数组元素想象成排队的人的身高,单调栈就是智能排队系统。准备好了吗?我们开整!


二、单调栈的基本概念:到底是个啥?

单调栈,顾名思义,就是栈内元素保持单调性(monotonic)。分两种类型:

  1. 单调递增栈:栈中元素从底到顶递增,就像排队时从矮到高。数学上,如果栈底元素是$a$,栈顶是$b$,那么$a \leq b$。
  2. 单调递减栈:栈中元素从底到顶递减,排队时从高到矮,即$a \geq b$。

为啥要单调?核心是利用单调性快速跳过无效比较。举个例子,假设数组是[2, 1, 4, 3],我们要找每个元素的“下一个更大元素”。用单调递减栈:

  • 遍历到2:栈空,直接入栈。
  • 遍历到1:1 < 2(栈顶),入栈(栈:[2,1])。
  • 遍历到4:4 > 1(栈顶),弹出1,记录1的下一个更大是4;4 > 2,弹出2,记录2的下一个更大是4;栈空,4入栈。
  • 遍历到3:3 < 4,入栈(栈:[4,3])。 结果:2→4, 1→4, 4→无, 3→无。看,只用一次遍历就搞定!

数学上,单调栈的单调性可以用不等式描述。对于单调递增栈,任意两个元素$s_i$和$s_j$($i < j$),满足: $$s_i \leq s_j$$ 类似地,单调递减栈满足: $$s_i \geq s_j$$ 这种结构让查找、插入、删除操作高效,时间复杂度通常是$O(n)$,因为每个元素只入栈出栈一次。

接地气理解:把它当成一个“智能过滤器”。数组元素一个个进来,栈自动踢掉不满足单调性的“弱者”,只留“强者”。这样,问题就简化了!


三、单调栈的工作原理:一步步拆解

现在,我们深入看看单调栈怎么工作。我会用找“下一个更大元素”(Next Greater Element)这个经典问题演示,接地气地说,就是“为每个人找右边第一个比他高的朋友”。

算法步骤(以单调递减栈为例):
  1. 初始化:创建一个空栈,用于存放数组索引(不是值,索引更方便)。
  2. 遍历数组:从左到右处理每个元素。
  3. 比较与弹出:如果当前元素 > 栈顶元素,说明栈顶元素找到了“下一个更大”(就是当前元素),弹出栈顶并记录结果。
  4. 入栈:当前元素入栈(保持栈的单调递减)。
  5. 收尾:遍历完后,栈中剩余元素没有“下一个更大”,记为-1或特定值。

伪代码更直观:

function nextGreater(arr):stack = empty stackresult = array of size n, initialized to -1for i from 0 to n-1:while stack not empty and arr[i] > arr[stack.top()]:index = stack.pop()result[index] = arr[i]  // 找到下一个更大stack.push(i)return result

实例演示:数组 [3, 1, 4, 2]
  • 步骤1:i=0, 元素3。栈空,入栈(栈:[0])。
  • 步骤2:i=1, 元素1。1 < 3(栈顶值),入栈(栈:[0,1])。
  • 步骤3:i=2, 元素4。4 > 1(栈顶值),弹出索引1,记录result[1]=4;4 > 3,弹出索引0,记录result[0]=4;栈空,入栈(栈:[2])。
  • 步骤4:i=3, 元素2。2 < 4,入栈(栈:[2,3])。
  • 结束:栈中剩余索引2和3,result[2]=-1, result[3]=-1。 结果:[4, 4, -1, -1]。完美!

为什么高效?时间复杂度$O(n)$,因为每个元素只入栈一次、出栈一次。空间复杂度$O(n)$,栈最多存n个元素。

接地气技巧:想象栈是个“候车室”,元素进来等“更大元素”出现。如果等到了,就离开;否则,一直等下去。单调性保证候车室不会乱。


四、C++实现:手把手教你写代码

理论懂了,来点实战!我用C++实现一个完整的单调栈应用——解决“下一个更大元素”问题。代码尽量简洁,加详细注释,接地气解释。

完整C++代码
#include <iostream>
#include <vector>
#include <stack>
using namespace std;// 函数:找到数组中每个元素的下一个更大元素
vector<int> nextGreaterElement(vector<int>& nums) {int n = nums.size();vector<int> result(n, -1);  // 初始化结果数组,默认-1表示无更大元素stack<int> st;  // 用栈存索引,保持单调递减// 遍历数组for (int i = 0; i < n; i++) {// 当栈不空且当前元素大于栈顶元素时,说明栈顶元素找到了"下一个更大"while (!st.empty() && nums[i] > nums[st.top()]) {int topIndex = st.top();  // 获取栈顶索引st.pop();  // 弹出栈顶result[topIndex] = nums[i];  // 记录结果}st.push(i);  // 当前元素入栈(索引)}return result;
}int main() {// 测试用例vector<int> arr = {3, 1, 4, 2};vector<int> result = nextGreaterElement(arr);// 输出结果cout << "原数组: ";for (int num : arr) cout << num << " ";cout << "\n下一个更大元素: ";for (int res : result) cout << res << " ";return 0;
}

代码详解(接地气版)
  • 头文件#include <stack> 引入栈,#include <vector> 用动态数组。
  • nextGreaterElement函数
    • vector<int> result(n, -1): 创建结果数组,初始-1(没找到更大元素)。
    • stack<int> st: 栈存索引,不是值。为啥?因为索引能定位元素,值比较时直接用nums[i]
    • 遍历循环for (int i = 0; i < n; i++) 逐个处理元素。
    • while条件!st.empty() && nums[i] > nums[st.top()] – 栈不空且当前元素大于栈顶元素?那就弹出栈顶并记录。
    • 入栈st.push(i) – 当前索引入栈,保持栈的单调递减。
  • main函数:测试数组[3,1,4,2],输出结果[4,4,-1,-1]。

编译运行(用g++):

g++ -o monotonic_stack monotonic_stack.cpp
./monotonic_stack

输出:

原数组: 3 1 4 2 
下一个更大元素: 4 4 -1 -1

为什么这样写?
  • 用索引存栈:避免值重复问题,比如数组有相同元素时。
  • 单调递减栈:适合找“下一个更大”;如果找“下一个更小”,就用单调递增栈。
  • 边界处理:数组为空时,代码也能处理(n=0,直接返回)。

接地气调试:加打印语句看栈变化。例如,在while循环里加cout << "弹出索引: " << topIndex << endl;,观察执行过程。


五、应用场景:单调栈能解决哪些问题?

单调栈不是花架子,它在算法题中超级实用。下面列举几个接地气的经典应用,全部来自LeetCode,我给出问题描述、解法思路和C++代码片段。

1. LeetCode 496: Next Greater Element I(简单题)
  • 问题:给定两个数组nums1和nums2,nums1是nums2的子集。找到nums1中每个元素在nums2中的下一个更大元素。
  • 解法:先用单调栈处理nums2,得到每个元素的下一个更大;然后用哈希表存结果,遍历nums1查询。
  • C++核心代码
    vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {stack<int> st;unordered_map<int, int> map; // 存nums2中元素的下一个更大for (int i = 0; i < nums2.size(); i++) {while (!st.empty() && nums2[i] > nums2[st.top()]) {map[nums2[st.top()]] = nums2[i];st.pop();}st.push(i);}// 处理nums1vector<int> result;for (int num : nums1) {result.push_back(map.count(num) ? map[num] : -1);}return result;
    }
    

2. LeetCode 503: Next Greater Element II(数组循环)
  • 问题:数组是环形的,找每个元素的下一个更大(循环查找)。
  • 解法:把数组拉直成两倍长度,再用单调栈。例如,数组[1,2,1]变成[1,2,1,1,2,1]。
  • C++核心代码
    vector<int> nextGreaterElements(vector<int>& nums) {int n = nums.size();vector<int> result(n, -1);stack<int> st;// 遍历两遍数组for (int i = 0; i < 2 * n; i++) {int num = nums[i % n]; // 循环索引while (!st.empty() && num > nums[st.top()]) {result[st.top()] = num;st.pop();}if (i < n) st.push(i); // 只存第一遍的索引}return result;
    }
    

3. LeetCode 84: Largest Rectangle in Histogram(难题,柱状图最大矩形)
  • 问题:给定柱状图的高度数组,求最大矩形面积。
  • 解法:用单调递增栈。遍历每个柱子,栈存索引;当当前柱子高度 < 栈顶时,弹出栈顶并计算以它为高的矩形面积。
  • C++核心代码
    int largestRectangleArea(vector<int>& heights) {stack<int> st;int maxArea = 0;heights.push_back(0); // 加哨兵值,处理剩余栈for (int i = 0; i < heights.size(); i++) {while (!st.empty() && heights[i] < heights[st.top()]) {int h = heights[st.top()]; // 当前高度st.pop();int width = st.empty() ? i : (i - st.top() - 1); // 计算宽度maxArea = max(maxArea, h * width);}st.push(i);}return maxArea;
    }
    

其他应用
  • 雨水收集问题(LeetCode 42):用单调栈算每个位置的积水。
  • 每日温度(LeetCode 739):找需要等几天才有更高温度。
  • 最大矩形(LeetCode 85):二维矩阵中找最大矩形,结合单调栈。

接地气总结:单调栈专治“找左邻居右邻居”的病。记住口诀:单调栈,顺序排;遇大弹出,遇小入栈;一次遍历,效率贼高!


六、实例分析:柱状图最大矩形详解

我们挑LeetCode 84题(柱状图最大矩形)深入分析,因为它是单调栈的招牌应用。接地气地说,就是“在高低不平的柱子里,找出能画出的最大长方形”。

问题描述

给定一个整数数组heights,表示柱状图的高度。例如,heights = [2,1,5,6,2,3],柱状图如下:

      ____| ||  | |__
__ |  | |  |
| || || || | 
------------2 1 5 6 2 3

求最大矩形面积(上图最大是10,来自高度5和6的柱子)。

单调栈解法思路

用单调递增栈(栈底到顶高度递增):

  1. 遍历柱子:每个柱子尝试入栈。
  2. 维护单调性:如果当前柱子高度 < 栈顶高度,说明栈顶柱子找到了右边界(当前索引),弹出栈顶。
  3. 计算面积:弹出时,以弹出柱子的高度为矩形高,宽度是右边界减左边界(左边界是栈新顶索引)。
  4. 哨兵技巧:在数组末尾加高度0的柱子,强制弹出所有栈中元素。
分步图解(以heights = [2,1,5,6,2,3]为例)
  • 步骤0:加哨兵,heights变成[2,1,5,6,2,3,0]。
  • i=0: 高度2,栈空,入栈(栈:[0])。
  • i=1: 高度1 < 2(栈顶),弹出索引0:
    • 高度h=2,栈空,宽度= i - 0 = 1(左边界是-1?实际用i=1),面积=2*1=2。
    • 入栈1(栈:[1])。
  • i=2: 高度5 > 1,入栈(栈:[1,2])。
  • i=3: 高度6 > 5,入栈(栈:[1,2,3])。
  • i=4: 高度2 < 6,弹出索引3:
    • h=6,栈顶索引2(高度5),宽度= i - 2 - 1 = 4-2-1=1,面积=6*1=6。
    • 高度2 < 5,弹出索引2:
      • h=5,栈顶索引1(高度1),宽度= i - 1 - 1 = 4-1-1=2,面积=5*2=10(最大)。
    • 入栈4(栈:[1,4])。
  • i=5: 高度3 > 2,入栈(栈:[1,4,5])。
  • i=6: 高度0 < 3,弹出索引5:
    • h=3,栈顶4(高度2),宽度=6-4-1=1,面积=3*1=3。
    • 高度0 < 2,弹出索引4:
      • h=2,栈顶1(高度1),宽度=6-1-1=4,面积=2*4=8。
    • 高度0 < 1,弹出索引1:
      • h=1,栈空,宽度=6,面积=1*6=6。
  • 结束:最大面积是10。
C++完整代码
#include <iostream>
#include <vector>
#include <stack>
using namespace std;int largestRectangleArea(vector<int>& heights) {heights.push_back(0); // 加哨兵值stack<int> st;int maxArea = 0;for (int i = 0; i < heights.size(); i++) {while (!st.empty() && heights[i] < heights[st.top()]) {int h = heights[st.top()];st.pop();int left = st.empty() ? -1 : st.top(); // 左边界索引int width = i - left - 1; // 宽度计算maxArea = max(maxArea, h * width);}st.push(i);}return maxArea;
}int main() {vector<int> heights = {2,1,5,6,2,3};cout << "最大矩形面积: " << largestRectangleArea(heights) << endl; // 输出10return 0;
}

为什么高效?
  • 时间复杂度$O(n)$:每个柱子只处理一次。
  • 空间复杂度$O(n)$:栈最多存n个索引。
  • 接地气提示:加哨兵(末尾0)是关键,确保所有柱子都被弹出计算。

练习:自己画图模拟过程,加深理解!


七、单调栈的优缺点:什么场合用?什么场合别用?

单调栈不是万能的,我们来客观看看它的好坏,接地气评价。

优点
  1. 高效省时:时间复杂度常是$O(n)$,比暴力法$O(n^2)$快得多。比如找下一个更大元素,暴力法要双重循环,单调栈一次遍历搞定。
  2. 代码简洁:C++实现通常20行以内,逻辑清晰。
  3. 应用广泛:特别适合“基于邻居元素”的问题,如LeetCode题、面试考点。
  4. 空间可控:空间复杂度$O(n)$,栈大小不超过数组长度。

接地气说:它像“智能导航”,帮你快速找到方向,避免绕弯路。

缺点
  1. 适用场景有限:只适合单调性问题。如果问题不涉及元素顺序(如求和、排序),就别硬套。
  2. 调试麻烦:栈操作容易出错,比如索引边界处理不当(左边界计算)。
  3. 理解门槛:初学者可能觉得抽象,需要多练习。
  4. 变体复杂:如单调队列(Monotonic Queue),进阶时更难。
使用建议
  • 推荐用:找下一个更大/更小元素、柱状图面积、雨水问题等。
  • 不推荐用:动态规划优化不直接相关时,或问题无单调性。
  • 接地气口诀:邻居顺序找单调,栈来帮忙快又好;若非此类别硬套,省时省力效率高。

八、进阶话题:单调队列和其他变体

单调栈只是入门,算法世界里还有更强大的工具。比如单调队列(Monotonic Queue),它能处理滑动窗口问题。接地气解释:单调栈是“单点过滤”,单调队列是“窗口过滤”。

单调队列简介
  • 定义:队列中元素保持单调性,常用于求滑动窗口最大值/最小值。
  • 例子:LeetCode 239: Sliding Window Maximum。
  • C++实现片段
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {deque<int> dq; // 双端队列存索引vector<int> result;for (int i = 0; i < nums.size(); i++) {// 移除超出窗口的元素if (!dq.empty() && dq.front() == i - k) dq.pop_front();// 维护单调递减(队头最大)while (!dq.empty() && nums[i] > nums[dq.back()]) dq.pop_back();dq.push_back(i);if (i >= k - 1) result.push_back(nums[dq.front()]);}return result;
    }
    

其他变体
  • 二维单调栈:处理矩阵问题,如LeetCode 85。
  • 结合动态规划:优化状态转移,减少计算。
  • 多栈组合:复杂问题用多个单调栈。

学习资源:

  • 书籍:《算法导论》有相关章节。
  • 在线:LeetCode标签“monotonic stack”,刷题巩固。
  • 视频:B站搜索“单调栈算法”,有实战讲解。

接地气建议:先精通单调栈,再挑战单调队列。每天刷一题,两周变高手!


九、总结:单调栈,算法小能手(约600字)

我们来回顾一下:

  • 单调栈是啥:保持元素单调顺序的栈,分递增和递减两种。
  • 怎么用:遍历数组,维护栈单调性,适时弹出计算。
  • C++实现:用std::stack,存索引,代码简洁高效。
  • 应用广:解决Next Greater Element、柱状图面积等经典问题。
  • 核心优势:时间复杂度$O(n)$,空间$O(n)$,接地气高效。

记住,算法学习就像健身——理论懂了,还得动手练。建议:

  1. 复现本文代码,理解每个步骤。
  2. 刷LeetCode题:496、503、84、42、739。
  3. 扩展:学习单调队列,玩转滑动窗口。

单调栈虽小,但威力巨大。掌握它,面试算法题不再怕!有问题随时交流,我们下篇文章见。


十、练习与资源

推荐练习题目(LeetCode)

  • 简单:496 (Next Greater Element I), 739 (Daily Temperatures)
  • 中等:503 (Next Greater Element II), 42 (Trapping Rain Water)
  • 困难:84 (Largest Rectangle in Histogram), 85 (Maximal Rectangle)

学习资源

  • 书籍:《算法竞赛入门经典》——刘汝佳(有C++实现)
  • 网站:LeetCode(搜索“monotonic stack”标签)
  • 视频教程:YouTube或B站“单调栈算法详解”(中文)

动手任务

  1. 用C++重写本文代码,加更多注释。
  2. 实现一个通用单调栈类,支持递增/递减模式。
  3. 尝试解决LeetCode 239(单调队列)。

算法路上,单调栈是你的好伙伴。坚持练习,你也能成为C++算法高手!如果有疑问,欢迎讨论。

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

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

相关文章

React入门指南——指北指南(第二节)

React 实践:创建你的第一个待办事项列表 在前面的章节中,我们学习了 React 的核心概念(组件、Props、State 等)。本节将通过一个实际案例——创建待办事项列表(Todo List),帮助你巩固这些概念,并掌握 React 中处理用户交互、动态数据的基本方法。 案例目标 我们将构…

WAIC看点:可交付AI登场,场景智能、专属知识将兑现下一代AI价值

7月28日&#xff0c;为期三天的2025世界人工智能大会&#xff08;WAIC 2025&#xff09;在上海落下帷幕。作为全球 AI 领域最受关注的盛会之一&#xff0c;今年 WAIC 聚焦 AI 关键命题&#xff0c;围绕大模型与智能体应用、算力新基建及大数据、智能终端与具身智能、AI金融、AI…

设计模式(十一)结构型:外观模式详解

设计模式&#xff08;十一&#xff09;结构型&#xff1a;外观模式详解外观模式&#xff08;Facade Pattern&#xff09;是 GoF 23 种设计模式中的结构型模式之一&#xff0c;其核心价值在于为一个复杂的子系统提供一个统一、简化的高层接口&#xff0c;从而降低客户端与子系统…

接口测试核心概念与实践指南

核心概念什么是接口&#xff1f;软件不同部分之间进行通信和数据交换的约定或契约。定义了&#xff1a;请求方 (Client/Consumer) 如何调用&#xff08;方法、URL、参数&#xff09;。提供方 (Server/Provider) 如何响应&#xff08;数据结构、状态码&#xff09;。双方需要遵循…

【NLP舆情分析】基于python微博舆情分析可视化系统(flask+pandas+echarts) 视频教程 - 热词数量分析日期统计功能实现

大家好&#xff0c;我是java1234_小锋老师&#xff0c;最近写了一套【NLP舆情分析】基于python微博舆情分析可视化系统(flaskpandasecharts)视频教程&#xff0c;持续更新中&#xff0c;计划月底更新完&#xff0c;感谢支持。今天讲解热词数量分析日期统计功能实现 视频在线地…

ICPC 2024 网络赛(I)

M. Find the Easiest Problem 题目大意 给定所有的提交记录&#xff0c;找到通过队伍最多且字典序最小的题目。 解题思路 按题意模拟即可 代码实现 #include <bits/stdc.h>using i64 long long;int main() {std::ios::sync_with_stdio(false);std::cin.tie(0);std…

【快捷指令】ios/macos快捷指令如何调用api接口(json请求例子)

一、步骤 之前已经写了一个【n8n】使用 n8n 创建插入数据到mysql的api&#xff08;图解步骤&#xff09;博客,感兴趣的可以看一下. 流程&#xff1a; 快捷指令调用api—开源工作流n8n上设置个快速写数据库的工作流 这样就实现了记录体重的一个快捷指令 二、步骤说明 1、…

「源力觉醒 创作者计划」_文心大模型4.5系列开源模型,意味着什么?对开发者、对行业生态有何影响?

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享一篇文章&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f495; 目录「源力…

CanMV-K230 AI学习笔记系列

在学习了一段时间CanMV-K230后&#xff0c;感觉虽然可以直接调用复杂的模型&#xff0c;但是很多环节不是很明白&#xff0c;因此希望能够从基础的模型开始逐渐深入学习。 下面为已经完成的一些笔记及计划&#xff1a; 1 CanMV K230使用经验分享 这个是刚开始学习K230时&#…

EtherCAT IGH别名(Alias)

EtherCAT 中的 Alias 是一个 16 位的数值&#xff0c;用于在拓扑结构中唯一标识从站&#xff08;除 Position 外的辅助定位方式&#xff09;IGH查看别名 “0:0”, 第一个0是别名(alias)&#xff0c;后面是位置(position) sudo ethercat slave -p 0 0 0:0 PREOP SV660_1Axi…

墨者:通过sqlmap解决SQL手工注入漏洞测试(PostgreSQL数据库)

使用Kali Linux中的sqlmap工具进行PostgreSQL手工注入漏洞测试实战 前言 SQL注入是Web安全中最常见的漏洞之一。本文将演示如何使用Kali Linux中的sqlmap工具对PostgreSQL数据库进行手工注入测试&#xff0c;通过实战案例帮助安全研究人员更好地理解漏洞原理和测试方法。 测…

Linux笔记5——常用命令-4

帮助命令man 命令&#xff08;查看命令的帮助&#xff09;注&#xff1a;C7版本中有中文解释例&#xff1a;man lsman -f 命令 #查看命令有哪些级别的帮助&#xff0c;使用前要执行mandb生成man缓存信息&#xff0c;否则命令执行不成功man级别1.查看命令的帮助3.查看函数…

优化Linux高并发:文件描述符与端口范围的协同调优

既然已经通过调整nofile&#xff08;最大文件描述符数量&#xff09;来支持高并发&#xff0c;为什么还需要调整net.ipv4.ip_local_port_range&#xff08;本地端口范围&#xff09;&#xff1f;这两个参数看似都与高并发有关&#xff0c;但它们的作用和影响范围不同。 1. 文件…

.NET-键控服务依赖注入

有时候我们在服务注册的时候会遇到这样一个场景&#xff0c;我们的同一个接口&#xff0c;有着多个实现&#xff0c;且我们还要同时使用这些实现的时候&#xff0c;这个时候该怎么办&#xff1f;我们可以使用键控服务依赖注入 键控服务依赖注入&#xff08;Keyed Dependency In…

VTK交互——ImageClip

概要 这段代码https://examples.vtk.org/site/Cxx/Interaction/ImageClip/实现了一个交互式图像裁剪工具,使用VTK库创建了一个双窗口界面,左侧显示原始图像,右侧显示裁剪后的图像。用户可以通过拖动边框小部件在左侧图像上选择裁剪区域,右侧窗口会实时显示裁剪结果。 代…

【vue vapor jsx 未雨绸缪】

随着vue3.6.0 alpha的发布&#xff0c;vapor mode进入正式版本只是时间上的问题&#xff0c;可以预见的是各个组件库都将积极适配vapor&#xff0c;这篇文章主要侧重vue中使用jsx而非SFC&#xff0c;所以不涉及template相关。目前vue官方也是提供了vue-jsx-vapor这个仓库&#…

go语言数据结构与排序算法

package mainimport "fmt"func main() {Bubble_Sort()Select_Sort()Insert_Sort()Shell_Sort()Heap_Sort()Merge_Sort()Quick_Sort() }一、1、冒泡排序 // 冒泡排序 func Bubble_Sort() {str : []int{9, 1, 5, 8, 3, 7, 4, 6, 2}// 正向冒泡for i : 0; i < len(st…

Petalinux生成文件的关系

1. 生成文件概述BOOT.BIN是引导程序&#xff0c;包括了 u-boot.elf是build u-boot生成的zynq_fsbl.elf&#xff08;引导PS和PL的启动&#xff09;elf文件是和启动引导相关的文件image.ub是镜像文件roofs.cpio.gz用来构建根文件系统

MongoDB的操作

在 Java 中操作 MongoDB 的 增删改查&#xff08;CRUD&#xff09; 主要有两种方式&#xff1a; Spring Data MongoDB&#xff08;推荐&#xff0c;类似 JPA 风格&#xff09;MongoDB Java Driver&#xff08;原生 API&#xff0c;更灵活&#xff09;1. Spring Data MongoDB 方…

getConnectionOwnerUid

在Android系统中&#xff0c;为了进行网络权限控制、流量统计等&#xff0c;需要将网络连接&#xff08;如Socket&#xff09;与发起该连接的应用UID关联起来。这种关联通常在内核中建立&#xff0c;并在用户空间通过一些接口进行查询。 1. 内核中的实现基础 Linux内核中&#…