C++STL剖析(六)—— set和multiset的概念和使用
文章目录
- 🌟 前言
- 🍑 树型结构和哈希结构
- 🍑 键值对
- 1. set的介绍和使用
- 🍑 set的模板参数列表
- 🍑 set的构造
- 🍑 set的使用
- 🍅 insert
- 🍅 find
- 🍅 erase
- 🍅 swap
- 🍅 empty
- 🍅 size
- 🍅 count
- 🍅 lower_bound
- 🍅 upper_bound
- 2. multiset的介绍和使用
- 🍑 multiset的使用
- 🍅 find
- 🍅 erase
- 🍅 count
- 3. 两个数组的交集
🌟 前言
在 STL 中主要有两种类型的容器:序列式容器 和 关联式容器:
- 序列式容器里面存储的是元素本身,其底层为线性序列的数据结构。比如:vector,list,deque,forward_list 等。
- 关联式容器里面存储的是
<key, value>结构的键值对,在数据检索时比序列式容器效率更高。比如:set,map,unordered_set,unordered_map 等。
但是有一点需要注意,STL 当中的 stack,queue 和 priority_queue 属于容器适配器。
stack 和 queue 默认使用的基础容器是 deque,而 priority_queue 使用的基础容器是 vector。
🍑 树型结构和哈希结构
根据应用场景的不同,STL 总共实现了两种不同结构的关联式容器:树型结构 和 哈希结构:

其中,树型结构容器中的元素是一个有序的序列,而哈希结构容器中的元素是一个无序的序列。
🍑 键值对
键值对是用来表示具有一一对应关系的一种结构,该结构中一般只包含两个成员变量 key 和 value,key 代表 键值,value 表示与 key 对应的信息。
比如:现在要建立一个英汉互译的字典,那该字典中必然有英文单词与其对应的中文含义,而且,英文单词与其中文含义是一一对应的关系,即通过该应该单词,在词典中就可以找到与其对应的中文含义。
SGI-STL 中关于键值对的定义方式如下:
template <class T1, class T2>
struct pair
{typedef T1 first_type;typedef T2 second_type;T1 first;T2 second;pair() : first(T1()), second(T2()){}pair(const T1& a, const T2& b) : first(a), second(b){}
};
1. set的介绍和使用
set 的介绍:
- set 是按照一定顺序存储元素的容器。
- 在 set 中,元素的 value 也标识它(value 就是 key,类型为 T),并且每个 value 必须是唯一的。set 中的元素不能在容器中修改(元素总是 const 类型),但是可以从容器中插入或删除它们。
- 在内部,set 中的元素总是按照其内部比较对象(类型为Compare)所指示的特定严格弱排序准则进行排序。
- set 容器通过 key 访问单个元素的速度通常比 unordered_set 容器慢,但 set 容器允许根据顺序对子集进行直接迭代。
- set 在底层是用二叉搜索树(红黑树)实现的。
注意:
- 与 map/multimap 不同,map/multimap 中存储的是真正的键值对
<key, value>,set 中只放 value,但在底层实际存放的是由<value, value>构成的键值对。 - set 中插入元素时,只需要插入 value 即可,不需要构造键值对。
- set 中的元素不可以重复(因此可以使用 set 进行去重)。
- 使用 set 的迭代器遍历 set 中的元素,可以得到有序序列
- set 中的元素默认按照小于来比较
- set 中查找某个元素,时间复杂度为:logNlogNlogN
- set中的元素不允许修改,因为 set 在底层是用二叉查找树来实现的,若是对二叉查找树当中某个结点的值进行了修改,那么这棵树将不再是二叉查找树。
🍑 set的模板参数列表
如下图所示:

T:set 中存放元素的类型,实际在底层存储<value, value>的键值对。Compare:set 中元素默认按照小于来比较。Alloc:set 中元素空间的管理方式,使用 STL 提供的空间配置器管理。
🍑 set的构造
这里主要有 3 种方式:

(1)无参构造一个空容器
set<int> s1; // 构造一个int类型的空容器
(2)拷贝构造某类型容器
set<int> s2(s1); // 拷贝构造int类型s1容器的复制品
(3)使用迭代器区间进行初始化构造
vector<int> v1 = { 1,2,3,4,5 };
set<int> s3(v1.begin(), v1.end()); // 构造vector对象某段区间的复制品
🍑 set的使用
set 的成员函数主要分为:迭代器,容量操作,修改操作。
需要注意的是,对于 set 而言,它的普通迭代器和 const 迭代器都不支持修改。

我这里只列举几个常用的,其它的可以看文档学习。
🍅 insert
在 set 中插入元素 val,实际插入的是 <val, val> 构成的键值对
- 如果插入成功,返回
<val在set中的位置, true> - 如果插入失败,说明 val 在 set 中已经存在,返回
<val在set中的位置, false>

代码示例
void testset()
{set<int> s;// 插入元素s.insert(4);s.insert(5);s.insert(2);s.insert(2);s.insert(1);s.insert(3);s.insert(3);// 遍历for (auto e : s){cout << e << " ";}
}
可以看到当插入重复元素时,set 的去掉了的,并且还进行了升序的排序

🍅 find
在容器中搜索查找 val 元素,如果找到,则返回一个迭代器,否则返回 set::end 的迭代器。

代码示例
void testset()
{set<int> s;// 插入元素s.insert(4);s.insert(5);s.insert(2);s.insert(2);s.insert(1);s.insert(3);s.insert(3);auto pos = s.find(5);if (pos != s.end()){cout << "找到了" << endl;}
}
运行结果

🍅 erase
删除 set 中的元素,这里有 3 种删除方式。

(1)从 set 容器中删除单个元素(搭配 find 使用)
void testset()
{set<int> s;// 插入元素s.insert(4);s.insert(5);s.insert(2);s.insert(1);s.insert(6);s.insert(3);s.insert(8);s.insert(7);auto pos = s.find(5);if (pos != s.end()){s.erase(pos); // 删除元素5cout << "删除成功" << endl;}else{cout << "删除失败" << endl;}// 遍历for (auto e : s){cout << e << " ";}
}
可以看到元素 5 已经被删除了

(2)从 set 容器中删除单个元素(直接传要删除的元素)
void testset()
{set<int> s;// 插入元素s.insert(4);s.insert(5);s.insert(2);s.insert(1);s.insert(6);s.insert(3);s.insert(8);s.insert(7);s.erase(5);// 遍历for (auto e : s){cout << e << " ";}
}
可以看到 5 已经被删除

那么它和第 1 种的区别是什么呢?
erase(x):如果 x 存在就删除;如果不存在,不做任何改变erase(pos):如果 x 存在就删除;如果不存在,此时 pos 位置指向set::end的迭代器,那么程序运行就会报错。
其实这种方式本质上可以理解为 erase 去调用了迭代器和 find。
(3)从 set 容器中删除一组元素(传的是迭代器区间 [first,last))
void testset()
{set<int> s;// 插入元素s.insert(4);s.insert(5);s.insert(2);s.insert(1);s.insert(6);s.insert(3);s.insert(8);s.insert(7);auto pos = s.find(5);if (pos != s.end()){s.erase(pos, s.end()); // 从5开始所有的元素全部删除cout << "删除成功" << endl;}else{cout << "删除失败" << endl;}// 遍历for (auto e : s){cout << e << " ";}
}
可以看到从 5 开始所有的元素都已经被删除

🍅 swap
交换 set 容器中的元素

代码示例
void testset()
{set<int> s1;s1.insert(4);s1.insert(5);s1.insert(2);s1.insert(1);set<int> s2;s2.insert(6);s2.insert(3);s2.insert(8);s2.insert(7);s1.swap(s2);cout << "s1:";// 遍历for (auto e1 : s1){cout << e1 << " ";}cout << "s2:";// 遍历for (auto e2 : s2){cout << e2 << " ";}
}
可以看到 s1 和 s2 的元素已经被交换了

🍅 empty
判断 set 容器是否为空,空返回 true,非空返回 false。

代码示例
void testset()
{set<int> s1;s1.insert(4);s1.insert(5);s1.insert(2);s1.insert(1);set<int> s2;cout << s1.empty() << endl; // s1容器不为空,输出0cout << s2.empty() << endl; // s2容器为空,输出1
}
运行结果

🍅 size
返回 set 中有效元素的个数

代码示例
void testset()
{set<int> s;// 插入元素s.insert(4);s.insert(5);s.insert(2);s.insert(1);s.insert(6);s.insert(3);s.insert(8);s.insert(7);// 打印元素个数cout << s.size() << endl;
}
运行结果

🍅 count
返回 set 中值为 x 的元素的个数。

代码示例
void testset()
{set<int> s;// 插入元素s.insert(4);s.insert(5);s.insert(2);s.insert(1);s.insert(6);s.insert(3);s.insert(8);s.insert(7);// 元素3的个数cout << s.count(3) << endl;// 元素7的个数cout << s.count(10) << endl;
}
可以看到 3 出现了一次,10 不存在

这个接口对于 set 容器其实没有太大用处,因为 set 当中的每个 value 都是唯一的。
🍅 lower_bound
返回一个指向容器中第一个元素的迭代器,该迭代器不被认为在val之前(它是等于或在val之后)
其实就是,返回大于等于 val 位置的迭代器。

代码示例一
void testset()
{set<int> s;// 插入元素s.insert(4);s.insert(5);s.insert(2);s.insert(1);s.insert(3);s.insert(8);s.insert(7);// 如果3存在就返回3位置的迭代器auto lowIt = s.lower_bound(3);cout << *lowIt << endl;// 如果6不存在就返回比6大的位置的迭代器lowIt = s.lower_bound(6);cout << *lowIt << endl;
}
运行结果

代码示例二
void testset()
{set<int> s;// 插入元素s.insert(4);s.insert(5);s.insert(2);s.insert(1);s.insert(3);s.insert(8);s.insert(7);// 删除大于等于4的所有值auto lowIt = s.lower_bound(4);s.erase(lowIt, s.end());// 遍历for (auto e : s){cout << e << " ";}
}
可以看到大于等于 4 的所有值都被删除了

🍅 upper_bound
返回指向容器中第一个元素的迭代器,该元素被认为是 val 之后的元素。
也就是说,不管 val 存在还是不存在,都返回比 val 大的那个值。

代码示例
void testset()
{set<int> s;// 插入元素s.insert(4);s.insert(5);s.insert(2);s.insert(1);s.insert(3);s.insert(8);s.insert(7);// 如果3存在就返回大于3位置的迭代器auto lowIt = s.upper_bound(3);cout << *lowIt << endl;// 如果6不存在就返回比6大的位置的迭代器lowIt = s.upper_bound(6);cout << *lowIt << endl;
}
运行结果

其实 lower_bound 和 upper_bound 可以搭配使用,删除元素中间的一段区间。
void testset()
{set<int> s;// 插入元素s.insert(4);s.insert(5);s.insert(2);s.insert(6);s.insert(1);s.insert(3);s.insert(8);s.insert(7);// 删除 [3, 7] 这段区间中的所有数auto leftIt = s.lower_bound(3); // 返回3位置的迭代器auto rightIt = s.upper_bound(7); // 返回8位置的迭代器s.erase(leftIt, rightIt);// 遍历for (auto e : s){cout << e << " ";}
}
注意,erase 删除的迭代器区间是左闭右开,也就是说 rightIt 是 8 位置的迭代器,但是 erase 只会删除到 7。
[3, 8) ⇒ [3, 7]

2. multiset的介绍和使用
multiset 的介绍:
- multiset 是按照特定顺序存储元素的容器,其中元素是可以重复的。
- 在 multiset 中,元素的 value 也会识别它(因为 multiset 中本身存储的就是
<value, value>组成的键值对,因此 value 本身就是 key,key 就是 value,类型为 T),multiset 元素的值不能在容器中进行修改(因为元素总是 const 的),但可以从容器中插入或删除。 - 在内部,multiset 中的元素总是按照其内部比较规则(类型比较)所指示的特定严格弱排序准则进行排序。
- multiset 容器通过 key 访问单个元素的速度通常比 unordered_multiset 容器慢,但当使用迭代器遍历时会得到一个有序序列。
- multiset 底层结构为二叉搜索树(红黑树)。
注意:
- multiset 中再底层中存储的是
<value, value>的键值对 - mtltiset 的插入接口中只需要插入即可
- 与 set 的区别是,multiset 中的元素可以重复,set 是中 value 是唯一的
- 使用迭代器对 multiset 中的元素进行遍历,可以得到有序的序列
- multiset 中的元素不能修改
- 在 multiset 中找某个元素,时间复杂度为O(logN)O(logN)O(logN)
- multiset 的作用:可以对元素进行排序
multiset的模板参数列表如下:

🍑 multiset的使用
当我们插入多个元素时,multiset 允许键值冗余,也就说 multiset 容器当中存储的元素是可以重复的。
代码示例
void testmultiset()
{multiset<int> ms;ms.insert(4);ms.insert(5);ms.insert(2);ms.insert(2);ms.insert(1);ms.insert(3);ms.insert(3);// 遍历for (auto e : ms){cout << e << " ";}
}
可以看到是存在多个相同元素的。

另外,它和 set 容器所提供的成员函数的接口都是基本一致的,所以就不全部列举了,只列举几个稍微有点小差别的函数接口。
🍅 find
在容器中搜索 val 元素,如果找到,则返回中序位置的第一个迭代器,否则返回 multiset::end 的迭代器。

代码示例
void testmultiset()
{multiset<int> ms;ms.insert(4);ms.insert(5);ms.insert(2);ms.insert(2);ms.insert(5);ms.insert(7);ms.insert(1);ms.insert(5);ms.insert(6);ms.insert(5);ms.insert(3);ms.insert(3);for (auto e : ms){cout << e << " ";}cout << endl;auto pos = ms.find(5); // 多个5的话,返回中序第一个5// 打印pos位置后面的所有元素while (pos != ms.end()){cout << *pos << " ";++pos;}
}
可以看到确实是从第一个 5 开始打印的

🍅 erase
从容器中删除单个元素,直接传要删除的话,erase 是的返回值是 size_type
它会把容器中所有的 val 全部删除,并且返回删除的 val 的个数。

代码示例
void testmultiset()
{multiset<int> ms;ms.insert(4);ms.insert(5);ms.insert(2);ms.insert(2);ms.insert(5);ms.insert(7);ms.insert(1);ms.insert(5);ms.insert(6);ms.insert(5);ms.insert(3);ms.insert(3);// 删除容器中所有的5,并返回5的个数cout << ms.erase(5) << endl;for (auto e : ms){cout << e << " ";}
}
可以看到元素 5 已经被删除了,并且元素个数是 4。

🍅 count
在容器中搜索等同于 val 的元素,并返回匹配的个数。

代码示例
void testmultiset()
{multiset<int> ms;ms.insert(4);ms.insert(3);ms.insert(2);ms.insert(2);ms.insert(5);ms.insert(7);ms.insert(1);ms.insert(3);ms.insert(6);ms.insert(5);ms.insert(3);// 统计3的个数cout << ms.count(3) << endl;// 遍历for (auto e : ms){cout << e << " ";}
}
运行结果

3. 两个数组的交集
题目描述

解题思路
对于求并集、交集、差集,其实有一种特定的方法,如下图所示:

代码实现
class Solution {
public:vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {// 去掉num1当中重复的元素并排序set<int> s1;for (auto e1 : nums1){s1.insert(e1);}// 去掉num2当中重复的元素并排序set<int> s2;for (auto e2 : nums2){s2.insert(e2);}vector<int> ret; // 存放交集auto it1 = s1.begin(); // 指向s1的起始位置auto it2 = s2.begin(); // 指向s2的起始位置while (it1 != s1.end() && it2 != s2.end()) // 当s1和s2都没有遍历完时{if (*it1 < *it2) {it1++;}else if (*it2 < *it1){it2++;}else // 当it1和it2指向的元素相等时,就是交集{ret.push_back(*it1); // 把元素尾插到ret中,然后同时向后挪动it1++;it2++;}}return ret; // 返回交集}
};
相关文章:
C++STL剖析(六)—— set和multiset的概念和使用
文章目录🌟 前言🍑 树型结构和哈希结构🍑 键值对1. set的介绍和使用🍑 set的模板参数列表🍑 set的构造🍑 set的使用🍅 insert🍅 find🍅 erase🍅 swap…...
SpringColud第四讲 Nacos的Windows安装方式和Linux的安装方式
在Nacos的GitHub页面,提供有下载链接,可以下载编译好的Nacos服务端或者源代码: 目录 1.Windows安装Nacos 1.1.下载 1.2.解压 1.3.修改相关配置: 1.4.启动: 1.5.登录: 2.Linux的安装方式Nacos 2.1.…...
微服务项目【网关服务限流熔断降级分布式事务】
网关服务限流熔断降级 第1步:启动sentinel-dashboard控制台和Nacos注册中心服务 第2步:在网关服务中引入sentinel依赖 <!-- sentinel --> <dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-…...
【情人节用Compose给女神写个爱心动画APP】
情人节用Compose给女神写个爱心动画APP前言涉及知识点实现思路实现过程绘制爱心创建动画效果Preview预览效果完整源码彩蛋前言 前一阵子看电视里的学霸用代码写了个炫酷的爱心,网上有很多js和python的源码,复制粘贴就能拥有,但是Android的好…...
GUI swing和awt
GUI(Graphical User Interface,简称 GUI,图形用户界面)是指采用图形方式显示的计算机操作用户界面,与早期计算机使用的命令行界面相比,图形界面对于用户来说在视觉上更易于接受。Java GUI主要有两个核心库&…...
速通Spring
尚硅谷2023最新版Spring6课程_bilibili 1 Spring 【强制】Spring是什么? 1) Spring是一款主流的Java EE轻量级开源框架。 轻量级:体积很小,且不需要依赖于其他组件。 2) 狭义的Spring。 Spring Framework。 3) 广义的Spring。 以Spring F…...
【C++】C++入门
一、 C关键字(C98) C有63个关键字(C语言有32个),如下: asmdoifreturntrycontinueautodoubleinlineshorttypedefforbooldynamic_castintsignedtypeidpublicbreakelselongsizeoftypenamethrowcaseenummutabl…...
Linux网络技术学习(五)—— 网络设备初始化(I)
文章目录什么时候进行的设备初始化?设备注册和初始化NIC(网卡 Network Interface Card)初始化的基本目标设备与内核之间的交互硬件中断中断类型传送节流方式为了改善效率中断共享IRQ处理函数映射的组织irqaction结构体存储方式什么时候进行的…...
[技术选型] ClickHouse和StarRocks的介绍
文章目录1.ClickHouse介绍2.StarRocks介绍1.ClickHouse介绍 ClickHouse是面向联机分析处理(OLAP)的开源分析引擎。最初由俄罗斯第一搜索引擎Yandex开发,于2016年开源,开发语言为C。由于其优良的查询性能,PB级的数据规…...
算法刷题打卡第90天:表现良好的最长时间段
表现良好的最长时间段 难度:中等 给你一份工作时间表 hours,上面记录着某一位员工每天的工作小时数。 我们认为当员工一天中的工作小时数大于 8 小时的时候,那么这一天就是「劳累的一天」。 所谓「表现良好的时间段」,意味在这…...
Python语言零基础入门教程(十七)
Python 文件I/O 本章只讲述所有基本的 I/O 函数,更多函数请参考Python标准文档。 #### 打印到屏幕 最简单的输出方法是用print语句,你可以给它传递零个或多个用逗号隔开的表达式。此函数把你传递的表达式转换成一个字符串表达式,并将结果写…...
C语言中大小端问题
目录 一、什么是大小端 二、 举个例子 三、大小端演示 四、解释"二"中举例的问题 五、怎么判断是大端还是小端 六、一个题目 一、什么是大小端 大端模式(大端字节序存储):就是高位字节数据存放在内存的低地址端ÿ…...
vue2+微前端qiankun从搭建到部署的实践(主子应用切换;集成vue3+vite3子应用)
一、最终效果 二、微前端(qiankun)介绍及为什么选择用微前端,可以看官网 三、目录结构如下 四、具体配置 一、主应用配置 1、主应用技术栈 Vue-cli4搭建项目Vue2Element-Uiqiankun;Vue2Element-Uiqiankun 2、搭建好主项目&…...
怎么代理微信小程序创业?
随着微信的兴起,小程序已经成为了人们生活中不可或缺的一部分。如果你想要创业的话,那么代理微信小程序是一个不错的选择。本文将为大家介绍怎么代理微信小程序创业。 一、什么是微信小程序 微信小程序是一款专为移动设备使用者而设计的应用。它通过扫…...
今天是情人节呐,我利用Python制作了好多表白的东西,快来吧~
今天是情人节那,有没有现在没有对象的宝子,评论里扣个111哈哈 目录 玫瑰 爱心树 丘比特 多彩气球 阿玥的小课堂 一、情人节的由来 二、情人节的来历和意义 玫瑰 局部代码实现如下: # 花瓣1 turtle.left(150) turtle.circle(-90, 70) …...
【Linux】-- 进程信号(处理、内核)
上篇:【Linux】-- 进程信号(认识、应用)_川入的博客-CSDN博客 目录 信号其他相关常见概念 pending handler block 信号处理的过程 sigset_t sigset_t使用 系统接口 sigpending sigprocmask 捕捉方法 sigaction struct sigactio …...
C/【静态通讯录】
🌱博客主页:大寄一场. 🌱系列专栏:C语言学习笔记 😘博客制作不易欢迎各位👍点赞⭐收藏➕关注 前言 往期回顾: C/扫雷 C/N子棋 通讯录作为通讯录地址的书本,当今的通讯录可以涵盖多项…...
万卷书 - 让孩子对自己负责 [The Self-Driven Child]
让孩子对自己负责 The Self-Driven Child - 让你的孩子更加科学合理的掌控自己的生活 简介 《The Self-Driven Child》(2018)解释了我们对孩子的习惯性控制欲,它导致了孩子压力过大、难以合作,以及主观能动性差。本书不提倡这种做法,而是认为我们应该帮助孩子自己做出合适…...
Postman中cookie的操作
在接口测试中,某些接口的调用,需要带入已有Cookie,比如有些接口需要登陆后才能访问。 Postman接口请求使用Cookie有如下两种方式: 1、直接在头域中添加Cookie头域,适用于已经知道请求所用Cookie数据的情况。 2、使用…...
torch.grid_sample
参考: 双线性插值的理论Pytorch grid_sample解析PyTorch中grid_sample的使用方法pytorch中的grid_sample()使用 查阅官方文档,TORCH.NN.FUNCTIONAL.GRID_SAMPLE grid_sample的函数签名如下所示,torch.nn.functional.grid_sample(input, gr…...
LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明
LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造,完美适配AGV和无人叉车。同时,集成以太网与语音合成技术,为各类高级系统(如MES、调度系统、库位管理、立库等)提供高效便捷的语音交互体验。 L…...
涂鸦T5AI手搓语音、emoji、otto机器人从入门到实战
“🤖手搓TuyaAI语音指令 😍秒变表情包大师,让萌系Otto机器人🔥玩出智能新花样!开整!” 🤖 Otto机器人 → 直接点明主体 手搓TuyaAI语音 → 强调 自主编程/自定义 语音控制(TuyaAI…...
Caliper 配置文件解析:config.yaml
Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO-BCOS 区块链网络的 Caliper 配置文件,主要包含以下几个部…...
视频行为标注工具BehaviLabel(源码+使用介绍+Windows.Exe版本)
前言: 最近在做行为检测相关的模型,用的是时空图卷积网络(STGCN),但原有kinetic-400数据集数据质量较低,需要进行细粒度的标注,同时粗略搜了下已有开源工具基本都集中于图像分割这块,…...
无人机侦测与反制技术的进展与应用
国家电网无人机侦测与反制技术的进展与应用 引言 随着无人机(无人驾驶飞行器,UAV)技术的快速发展,其在商业、娱乐和军事领域的广泛应用带来了新的安全挑战。特别是对于关键基础设施如电力系统,无人机的“黑飞”&…...
Selenium常用函数介绍
目录 一,元素定位 1.1 cssSeector 1.2 xpath 二,操作测试对象 三,窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四,弹窗 五,等待 六,导航 七,文件上传 …...
【JVM】Java虚拟机(二)——垃圾回收
目录 一、如何判断对象可以回收 (一)引用计数法 (二)可达性分析算法 二、垃圾回收算法 (一)标记清除 (二)标记整理 (三)复制 (四ÿ…...
NPOI操作EXCEL文件 ——CAD C# 二次开发
缺点:dll.版本容易加载错误。CAD加载插件时,没有加载所有类库。插件运行过程中用到某个类库,会从CAD的安装目录找,找不到就报错了。 【方案2】让CAD在加载过程中把类库加载到内存 【方案3】是发现缺少了哪个库,就用插件程序加载进…...
Linux部署私有文件管理系统MinIO
最近需要用到一个文件管理服务,但是又不想花钱,所以就想着自己搭建一个,刚好我们用的一个开源框架已经集成了MinIO,所以就选了这个 我这边对文件服务性能要求不是太高,单机版就可以 安装非常简单,几个命令就…...
数据结构第5章:树和二叉树完全指南(自整理详细图文笔记)
名人说:莫道桑榆晚,为霞尚满天。——刘禹锡(刘梦得,诗豪) 原创笔记:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 上一篇:《数据结构第4章 数组和广义表》…...
