有序之美:C++ Set的哲学与诗意
文章目录
- 前言
- 一.C++ set 的概念
- 1.1 set 的定义
- 1.2 set 的特点
- 二. set 的构造方法
- 2.1 常见构造函数
- 2.1.1 示例:不同构造方法
- 2.2 相关文档
- 三.set 的常用操作
- 3.1 插入操作详解
- 3.1.1 使用 insert() 插入元素
- 3.1.2 使用 emplace() 插入元素
- 3.1.3 插入区间元素
- 3.2 查找操作详解
- 3.2.1 使用 find() 查找元素
- 3.2.2 使用 count() 统计元素
- 3.3 删除操作详解
- 3.3.1 使用 erase() 删除单个元素
- 3.3.2 使用迭代器区间删除元素
- 3.3.3 清空 set
- 四.set 的常用成员函数
- 4.1 常用成员函数概述
- 4.2 成员函数示例
- 4.2.1 begin() 和 end()
- 4.2.2 rbegin() 和 rend()
- 4.2.3 size() 和 empty()
- 4.2.4 max_size()
- 4.2.5 swap()
- 五.性能分析
- 5.1 时间复杂度
- 5.2 空间复杂度
- 5.3 性能优化建议
- 六. 高级用法
- 6.1 自定义排序和比较器
- 6.1.1 示例:自定义比较器
- 6.2 使用迭代器进行复杂操作
- 6.2.1 示例:使用迭代器删除特定条件下的元素
- 6.2.2 示例:逆向遍历 set
- 七. multiset 的使用
- 7.1 multiset 与 set 的区别
- 7.2 使用 multiset 存储重复键
- 7.3 multiset 的常用操作
- 7.3.1 使用 count() 统计元素
- 7.3.2 使用 equal_range() 查找范围
- 7.3.3 删除特定的重复元素
- 7.4 使用场景
- 小结

前言
有序之美:C++ Set的哲学与诗意
在C++的繁华语言世界中,有一个数据结构宛如一位端庄优雅的隐士,它不事张扬,却蕴藏着深邃的智慧与独特的魅力。这便是标准模板库(STL)中的set容器。若将C++比作一幅绚丽的画卷,set则如点缀画卷的灵动笔触,简单而不失精妙。
一.C++ set 的概念
1.1 set 的定义
set 是 C++ STL 中的一种关联式容器,专为存储唯一元素而设计。它提供了自动排序和高效的查找操作,元素总是根据特定顺序(默认是升序)排列。
- 唯一性:每个元素在 set 中是唯一的,插入重复元素时,新元素不会覆盖旧元素,且插入会被忽略。
- 自动排序:set 容器根据元素的顺序关系自动排序。默认情况下使用 < 运算符进行比较。
(升序)
- 底层实现:set 使用红黑树实现,确保数据结构在插入、查找和删除操作上的平衡性和高效性。
set 容器的这些特性使其成为去重和自动排序操作的理想选择,并在 O(log N)
的时间复杂度下提供快速的查找、插入和删除操作。
1.2 set 的特点
- 有序性:与 unordered_set 不同,set 会根据元素值自动排序,通常使用升序排列。排序操作由内部的红黑树维护。
- 高效查找:set 适用于频繁查找的场景,查找时间复杂度为 O(log N)。
- 动态数据支持:支持动态的插入和删除,能够适应需要频繁更新的数据集。
- 不允许重复元素:在 set 中,元素的值即为键,不存在重复值。若需要存储重复值,请使用 multiset。
二. set 的构造方法
2.1 常见构造函数
set 提供了多种构造函数,以便用户根据需求灵活初始化容器。以下是 set 常用的构造方法和功能:
2.1.1 示例:不同构造方法
默认构造函数:
创建一个空的 set。
#include <iostream>
#include <set>
using namespace std;int main() {set<int> mySet; // 空的 set 容器cout << "Size of mySet: " << mySet.size() << endl; // 输出: 0return 0;
}
区间构造函数
:用 [first, last) 区间内的元素构造 set。适用于将已有容器的一部分元素导入 set。
#include <iostream>
#include <set>
#include <vector>
using namespace std;int main() {vector<int> nums = {3, 1, 4, 1, 5, 9};set<int> mySet(nums.begin(), nums.end()); // 从 vector 初始化for (const auto& elem : mySet) {cout << elem << " "; // 输出: 1 3 4 5 9 (自动去重并排序)}return 0;
}
拷贝构造函数:
生成一个与已有 set 容器相同的拷贝。
#include <iostream>
#include <set>
using namespace std;int main() {set<int> originalSet = {1, 2, 3};set<int> copySet(originalSet); // 拷贝构造for (const auto& elem : copySet) {cout << elem << " "; // 输出: 1 2 3}return 0;
}
初始化列表构造:
使用初始化列表来初始化 set 容器。
#include <iostream>
#include <set>
using namespace std;int main() {set<int> mySet = {2, 7, 1, 8, 2, 8}; // 自动去重并排序for (const auto& elem : mySet) {cout << elem << " "; // 输出: 1 2 7 8}return 0;
}
解释:
- 使用 {} 初始化列表会将相同元素自动去重,且 set 会按照升序排序。
- 区间构造、拷贝构造和初始化列表构造都非常适合在需要从其他数据结构中导入数据时使用。
2.2 相关文档
https://cplusplus.com/reference/set/set/set/
三.set 的常用操作
3.1 插入操作详解
插入操作是 set 容器的基础操作之一,set 提供了多种插入元素的方法。由于 set 中不允许重复元素,每次插入操作后,set 会自动去重。
3.1.1 使用 insert() 插入元素
insert() 是 set 中最常用的插入方法。它不仅可以插入单个元素,还可以插入区间元素或初始化列表。
#include <iostream>
#include <set>
using namespace std;int main() {set<int> mySet;// 插入单个元素mySet.insert(5);mySet.insert(3);mySet.insert(8);// 插入初始化列表中的所有元素mySet.insert({2, 7, 1});for (const auto& elem : mySet) {cout << elem << " "; // 输出: 1 2 3 5 7 8 (自动排序)}return 0;
}
解释:
- insert() 方法会返回一个
pair
,其 first 元素是指向插入位置的迭代器,second 元素是一个布尔值,表示插入是否成功(当元素已存在时为 false)。
3.1.2 使用 emplace() 插入元素
emplace() 允许直接在 set 中构造元素,避免不必要的复制,提高插入效率。与 insert() 相比,emplace() 更高效,尤其在处理复杂对象时。
#include <iostream>
#include <set>
using namespace std;int main() {set<int> mySet;// 使用 emplace 插入元素mySet.emplace(10);mySet.emplace(4);mySet.emplace(6);for (const auto& elem : mySet) {cout << elem << " "; // 输出: 4 6 10 (自动排序)}return 0;
}
解释:
- emplace() 方法直接在 set 中构造元素,适用于插入对象的构造比较复杂且不希望进行复制的情况。
3.1.3 插入区间元素
可以使用 insert() 方法从另一个容器中插入一个区间的元素。
#include <iostream>
#include <set>
#include <vector>
using namespace std;int main() {vector<int> nums = {6, 4, 6, 7, 8}; // 有重复元素set<int> mySet;mySet.insert(nums.begin(), nums.end()); // 插入 vector 的元素for (const auto& elem : mySet) {cout << elem << " "; // 输出: 4 6 7 8 (自动去重和排序)}return 0;
}
解释:
- 通过 insert(nums.begin(), nums.end()) 可以从已有容器中导入数据,并在插入时去重和排序。
3.2 查找操作详解
查找操作可以帮助我们在 set 中验证元素是否存在。set 提供了多个方法来实现查找操作。
3.2.1 使用 find() 查找元素
find() 方法返回一个迭代器,指向指定元素的位置,如果元素不在 set 中,则返回 end() 迭代器。
#include <iostream>
#include <set>
using namespace std;int main() {set<int> mySet = {3, 6, 9};auto it = mySet.find(6);if (it != mySet.end()) {cout << "Found: " << *it << endl; // 输出: Found: 6} else {cout << "Not found" << endl;}return 0;
}
解释:
- find() 方法返回指向查找元素的迭代器,若元素不存在则返回 end()。
3.2.2 使用 count() 统计元素
count()
方法返回指定元素的数量。对于 set,因为元素唯一,结果要么是 0 要么是 1。
#include <iostream>
#include <set>
using namespace std;int main() {set<int> mySet = {1, 4, 9};cout << "Count of 4: " << mySet.count(4) << endl; // 输出: Count of 4: 1cout << "Count of 7: " << mySet.count(7) << endl; // 输出: Count of 7: 0return 0;
}
解释:
- 因为 set 不允许重复元素,所以 count() 只能返回 0 或 1。
3.3 删除操作详解
删除操作允许我们从 set 中移除特定元素或区间。
3.3.1 使用 erase() 删除单个元素
erase()
方法可以通过值或迭代器来删除元素。
#include <iostream>
#include <set>
using namespace std;int main() {set<int> mySet = {2, 4, 6, 8};mySet.erase(4); // 删除值为 4 的元素for (const auto& elem : mySet) {cout << elem << " "; // 输出: 2 6 8}return 0;
}
解释:
erase()
方法可以根据值删除元素,若元素不存在则不会进行任何操作。
3.3.2 使用迭代器区间删除元素
erase()
还支持根据迭代器区间来删除一组元素。
#include <iostream>
#include <set>
using namespace std;int main() {set<int> mySet = {1, 2, 3, 4, 5};auto it1 = mySet.find(2);auto it2 = mySet.find(4);mySet.erase(it1, it2); // 删除 [2, 4) 区间内的元素,不包含 4for (const auto& elem : mySet) {cout << elem << " "; // 输出: 1 4 5}return 0;
}
解释:
- erase(it1, it2) 删除的是从迭代器 it1 到 it2(不包含 it2)的元素。
3.3.3 清空 set
使用 clear() 方法可以清空整个 set。
#include <iostream>
#include <set>
using namespace std;int main() {set<int> mySet = {3, 5, 7};mySet.clear(); // 清空 setcout << "Size after clear: " << mySet.size() << endl; // 输出: Size after clear: 0return 0;
}
解释:
clear()
方法会删除 set 中的所有元素,将 set 大小变为 0。
四.set 的常用成员函数
set 容器提供了一系列成员函数,使用户能够方便地进行数据操作和信息查询。在本节中,将详细介绍这些常用的成员函数及其用法。
4.1 常用成员函数概述
4.2 成员函数示例
4.2.1 begin() 和 end()
begin()
返回指向 set 第一个元素的迭代器,end()
返回指向 set 尾后位置的迭代器。
#include <iostream>
#include <set>
using namespace std;int main() {set<int> mySet = {5, 10, 15};for (auto it = mySet.begin(); it != mySet.end(); ++it) {cout << *it << " "; // 输出: 5 10 15}return 0;
}
4.2.2 rbegin() 和 rend()
rbegin()
返回指向 set 最后一个元素的反向迭代器,rend()
返回指向 set 第一个元素之前位置的反向迭代器。
#include <iostream>
#include <set>
using namespace std;int main() {set<int> mySet = {3, 6, 9};for (auto it = mySet.rbegin(); it != mySet.rend(); ++it) {cout << *it << " "; // 输出: 9 6 3}return 0;
}
4.2.3 size() 和 empty()
size()
返回 set 中的元素个数,empty()
用于检查 set 是否为空。
#include <iostream>
#include <set>
using namespace std;int main() {set<int> mySet = {1, 2, 3};cout << "Size of mySet: " << mySet.size() << endl; // 输出: Size of mySet: 3cout << "Is mySet empty? " << (mySet.empty() ? "Yes" : "No") << endl; // 输出: NomySet.clear(); // 清空 mySetcout << "Size after clear: " << mySet.size() << endl; // 输出: 0cout << "Is mySet empty? " << (mySet.empty() ? "Yes" : "No") << endl; // 输出: Yesreturn 0;
}
4.2.4 max_size()
max_size()
返回 set 可以容纳的最大元素数量。
#include <iostream>
#include <set>
using namespace std;int main() {set<int> mySet;cout << "Max size of mySet: " << mySet.max_size() << endl; // 输出一个很大的数,表示最大可能容量return 0;
}
4.2.5 swap()
swap()
用于交换两个 set 容器的内容。
#include <iostream>
#include <set>
using namespace std;int main() {set<int> set1 = {1, 3, 5};set<int> set2 = {2, 4, 6};set1.swap(set2); // 交换 set1 和 set2 的内容cout << "Elements in set1: ";for (const auto& elem : set1) {cout << elem << " "; // 输出: 2 4 6}cout << "\nElements in set2: ";for (const auto& elem : set2) {cout << elem << " "; // 输出: 1 3 5}return 0;
}
解释:
- swap() 函数交换两个 set 的内容,但不会影响各自的容量或分配。
五.性能分析
5.1 时间复杂度
C++ 的 set 容器基于红黑树实现,因此在大部分操作中具备较高的效率。以下是 set 常用操作的时间复杂度分析:
-
插入 (insert):
时间复杂度为 O(log N)。由于 set 使用平衡二叉树维护元素的有序性,每次插入操作需要找到合适的插入位置,因此为 O(log N)。 -
查找 (find):
时间复杂度为 O(log N)。在 set 中查找特定元素时,借助红黑树的性质可以在 O(log N) 时间内完成查找。 -
删除 (erase)
:时间复杂度为 O(log N)。删除操作需要定位待删除元素的位置,并调整树的平衡结构,因此复杂度为 O(log N)。 -
遍历:
遍历整个 set 的时间复杂度为 O(N)。由于 set 是有序的,遍历操作是顺序的,因此与元素数量成线性关系。
5.2 空间复杂度
-
空间复杂度:set 的空间复杂度通常为 O(N),其中 N 表示 set 中存储的元素个数。由于 set 基于红黑树实现,每个节点包含元素值及指向子节点的指针,因此在存储元素之外需要额外的指针空间。
-
内存管理:set 使用了动态内存分配,在插入和删除元素时,内存会动态调整,以确保红黑树的平衡。虽然 set 内部使用红黑树存储元素,但 STL 已优化了 set 的内存分配,使其尽可能地降低内存浪费。
5.3 性能优化建议
-
避免频繁的插入和删除操作:虽然 set 在插入和删除操作上表现良好,但大量的插入或删除操作仍会影响性能。如果数据量很大且操作频繁,建议考虑 unordered_set,其基于哈希表实现,在插入和删除操作上的平均时间复杂度为 O(1)。
-
适用场景:set 适用于需要有序存储且不允许重复元素的场景,例如需要自动排序的场景,或在大数据量中频繁查找特定元素时。
-
空间与时间的平衡:set 需要较多内存来维护树的平衡,因此在嵌入式系统或内存受限的环境下使用时需谨慎。
六. 高级用法
6.1 自定义排序和比较器
默认情况下,set 使用 < 运算符按升序排序元素 不过,在某些情况下,我们可能需要使用自定义的排序规则。C++ set 容器允许使用自定义比较器,以实现自定义的排序方式。
6.1.1 示例:自定义比较器
可以通过自定义比较器来实现降序排列。自定义比较器可以是一个函数对象或函数
#include <iostream>
#include <set>
using namespace std;// 定义一个比较器,使 set 按降序排列
struct DescendingOrder {bool operator()(const int& a, const int& b) const {return a > b;}
};int main() {set<int, DescendingOrder> mySet; // 使用自定义比较器mySet.insert(3);mySet.insert(1);mySet.insert(4);mySet.insert(2);for (const auto& elem : mySet) {cout << elem << " "; // 输出: 4 3 2 1}return 0;
}
解释:
- DescendingOrder 是一个结构体,实现了降序排列的 operator() 函数。在定义 set 时将该比较器传入,实现了 set 的降序排列。
- 应用场景:自定义比较器适用于需要特殊排序逻辑的情况,比如按字符串长度排序或按特定规则排列数据。
6.2 使用迭代器进行复杂操作
set 容器的迭代器支持多种操作,适合在遍历、条件删除等场景中使用。以下介绍迭代器在复杂操作中的应用。
6.2.1 示例:使用迭代器删除特定条件下的元素
可以使用迭代器遍历 set,并根据条件删除符合要求的元素。例如,删除所有偶数元素。
#include <iostream>
#include <set>
using namespace std;int main() {set<int> mySet = {1, 2, 3, 4, 5, 6};for (auto it = mySet.begin(); it != mySet.end(); ) {if (*it % 2 == 0) {it = mySet.erase(it); // 删除偶数元素并更新迭代器} else {++it;}}for (const auto& elem : mySet) {cout << elem << " "; // 输出: 1 3 5}return 0;
}
解释:
- 使用 erase() 删除元素时会返回一个新的迭代器,指向被删除元素的下一个位置。删除时务必更新迭代器以避免迭代器失效。
6.2.2 示例:逆向遍历 set
利用 rbegin()
和 rend()
,可以对 set 进行逆向遍历。
#include <iostream>
#include <set>
using namespace std;int main() {set<int> mySet = {10, 20, 30, 40};for (auto it = mySet.rbegin(); it != mySet.rend(); ++it) {cout << *it << " "; // 输出: 40 30 20 10}return 0;
}
解释:
rbegin()
和 rend()
分别返回指向 set 容器最后一个元素和第一个元素之前位置的反向迭代器,实现逆序遍历。
七. multiset 的使用
multiset
是 C++ STL 中的另一种关联容器,与 set 类似,但允许重复元素。multiset
的主要特点是能存储多个相同的键值,并按照键值顺序自动排序。它适用于需要频繁计数或存储重复数据的场景。
7.1 multiset 与 set 的区别
7.2 使用 multiset 存储重复键
multiset
容器可以有效地存储和管理重复的键值。以下示例展示了如何在 multiset
中插入重复的键值。
#include <iostream>
#include <set>
using namespace std;int main() {multiset<int> myMultiSet;myMultiSet.insert(5);myMultiSet.insert(5);myMultiSet.insert(3);myMultiSet.insert(3);for (const auto& elem : myMultiSet) {cout << elem << " "; // 输出: 3 3 5 5}return 0;
}
解释:
在 multiset 中,即使是相同的键(如 3 和 5),每次插入操作都会保留重复值。
7.3 multiset 的常用操作
multiset 支持的操作与 set 类似,但针对重复元素的操作略有不同,以下列出几个常用操作。
7.3.1 使用 count() 统计元素
count()
方法可以统计特定元素的出现次数。
#include <iostream>
#include <set>
using namespace std;int main() {multiset<int> myMultiSet = {1, 1, 2, 3, 3, 3};cout << "Count of 1: " << myMultiSet.count(1) << endl; // 输出: 2cout << "Count of 3: " << myMultiSet.count(3) << endl; // 输出: 3return 0;
}
解释:
count()
方法返回特定元素在 multiset 中的出现次数。
7.3.2 使用 equal_range() 查找范围
equal_range()
方法返回一个范围,表示特定元素的所有匹配项。
#include <iostream>
#include <set>
using namespace std;int main() {multiset<int> myMultiSet = {2, 2, 3, 3, 3, 4};auto range = myMultiSet.equal_range(3); // 获取键为 3 的范围for (auto it = range.first; it != range.second; ++it) {cout << *it << " "; // 输出: 3 3 3}return 0;
}
解释:
equal_range()
返回一个 pair,其中 first 为指定元素的第一个位置,second 为指定元素的最后一个位置(不含 second)。
7.3.3 删除特定的重复元素
erase()
方法可以删除指定元素的一个或所有出现次数。
#include <iostream>
#include <set>
using namespace std;int main() {multiset<int> myMultiSet = {2, 3, 3, 4};myMultiSet.erase(myMultiSet.find(3)); // 删除第一个 3for (const auto& elem : myMultiSet) {cout << elem << " "; // 输出: 2 3 4}return 0;
}
解释:
erase()
删除迭代器指定位置的元素,仅删除一次。若要删除所有相同元素,可直接传入键值。
myMultiSet.erase(3); // 删除所有键为 3 的元素
7.4 使用场景
- 重复记录:在存储包含重复项的数据时(如多个学生的成绩或产品订单),multiset 能提供灵活的管理方式。
- 频率统计:当需要对某些值进行频率统计时,multiset 可以用来存储和快速统计每个元素的出现次数。
- 分类存储:适合在需要分类存储数据并保留重复记录的场景中使用,比如管理多个分数段的学生记录。
小结
在程序世界中,set像是一位哲人,它教会我们如何在规则中追求秩序,又如何在有序中寻求高效。在处理数据的过程中,set常常成为开发者的得力助手,为复杂的逻辑注入优雅的简洁。
如果你愿意走近set,你会发现它并不只是一个简单的数据结构,而是C++语言中一颗璀璨的明珠。在这片有序的天地里,set以它独特的规则与高效的实现,让我们感受到编程的艺术之美。每一行代码的编写,都是对这位隐士的一次致敬。
本篇关于STL容器中set的介绍就暂告段落啦,希望能对大家的学习产生帮助,欢迎各位佬前来支持斧正!!!
相关文章:
有序之美:C++ Set的哲学与诗意
文章目录 前言一.C set 的概念1.1 set 的定义1.2 set 的特点二. set 的构造方法2.1 常见构造函数2.1.1 示例:不同构造方法 2.2 相关文档 三.set 的常用操作3.1 插入操作详解3.1.1 使用 insert() 插入元素3.1.2 使用 emplace() 插入元素3.1.3 插入区间元素 3.2 查找操…...
22. 仿LISP运算
题目描述 LISP语言唯一的语法就是括号要配对 形如(OP P1 P2 ...),括号内元素由单个空格分割。其中第一个元素OP为操作符,后续元素均为其参数,参数个数取决于操作符类型。注意:参数P1,P2也有可能是另外一个嵌套的(OP P1 P2...),当前…...
大模型应用技术系列(三): 深入理解大模型应用中的Cache:GPTCache
前言 无论在什么技术栈中,缓存都是比较重要的一部分。在大模型技术栈中,缓存存在于技术栈中的不同层次。本文将主要聚焦于技术栈中应用层和底层基座之间中间件层的缓存(个人定位),以开源项目GPTCache(LLM的语义缓存)为例,深入讲解这部分缓存的结构和关键实现。 完整技术…...
MATLAB语言的网络编程
标题:MATLAB中的网络编程:深入探索与实践 一、引言 在现代科学和工程领域中,网络编程已经成为了数据处理、信号分析、模型构建等众多任务中不可或缺的一环。MATLAB作为一款强大的数学计算软件,不仅提供了丰富的数值计算功能&…...
边缘计算收益稳定
要使自己的PCDN(Personal Content Delivery Network,个人内容分发网络)收益更稳定,可以从以下几个方面进行努力: 一、选择合适的PCDN平台 平台稳定性:选择技术成熟、稳定性高的PCDN平台,确保内…...
计算机网络 (7)物理层下面的传输媒体
一、定义与位置 物理层是计算机网络体系结构的最低层,它位于传输媒体(传输介质)之上,主要作用是为数据链路层提供一个原始比特流的物理连接。这里的“比特流”是指数据以一个个0或1的二进制代码形式表示。物理层并不是特指某种传输…...
【GoPL】1.2 命令行参数
1.2 命令行参数 24-12-26 大部分程序处理输入,然后产生一些输出,这大概有点像计算的定义 但是程序怎么操作输入的数据?(用参数来操作)输入可能来自文件、网络连接、用户的键盘输入、命令行参数(不同的编程范式) os包提供函数和其他值来处理…...
高精度问题
目录 算法实现基础 高精度加法AB 测试链接 源代码 代码重点 高精度减法A-B 测试链接 源代码 代码重点 高精度乘法A*b和A*B 测试链接 源代码 代码重点 高精度除法A/b和A/B 测试链接 源代码 代码重点 高精度求和差积商余 算法实现基础 本算法调用STL…...
【无线通信】蜂窝系统——干扰与系统容量
干扰是蜂窝无线系统性能的主要限制因素。干扰来源包括同一小区中的其他移动终端、邻近小区正在进行的通话、其他基站在同一频段内的工作信号,或者任何不属于蜂窝系统的设备偶然向蜂窝频段泄漏信号。语音信道中的干扰会导致串音,使得用户在通话时听到背景…...
深入探索仓颉编程语言:函数与结构类型的终极指南
引言 仓颉编程语言是一种现代化、语法精炼的编程语言,其设计目标是提供高度的灵活性与高性能的执行效率。函数与结构类型是仓颉语言的两大基础模块,也是开发者需要掌握的核心。本文将详细讲解仓颉语言中函数和结构类型的特性,辅以代码实例和…...
010-spring-后置处理器(重要)
org.mybatis.spring.mapper.MapperScannerConfigurer...
SQL实现新年倒计时功能
马上就到 2025 年了,给大家分享一个使用 SQL 实现的新年倒计时功能。 以下是 PostgreSQL 语法: DO $$ DECLAREdiff INTERVAL; BEGINRAISE NOTICE 2025新年倒计时开始:;LOOP-- 计算当前时间距离2025年的时间间隔diff age(timestamp 2025-01…...
list模拟实现
目录 节点结构 构造函数 insert erase push_back push_front pop_front pop_back 拷贝构造 析构函数 赋值重载 正向迭代器实现 clear 反向迭代器实现 测试list 附完整代码 参照数据结构篇: 带头双向循环链表 节点结构 namespace dck {template <class T&g…...
JVM【Java虚拟机】基础知识(五)
1. 双亲委派机制 由于Java虚拟机中有多个类加载器,双亲委派机制的核心是解决一个类到底由谁加载的问题。 💡双亲委派机制有什么用? 1.保证类加载的安全性 通过双亲委派机制避免恶意代码替换JDK中的核心类库,比如java.lang.Str…...
阿尔萨斯(JVisualVM)JVM监控工具
文章目录 前言阿尔萨斯(JVisualVM)JVM监控工具1. 阿尔萨斯的功能2. JVisualVM启动3. 使用 前言 如果您觉得有用的话,记得给博主点个赞,评论,收藏一键三连啊,写作不易啊^ _ ^。 而且听说点赞的人每天的运气都不会太差ÿ…...
Vue BPMN Modeler流程图
1、参考地址 git clone https://github.com/evanyangg/vue-bpmn-modeler.git 2、安装bpmn.js npm install bpmn-js --save 3、使用bpmn.js <template><div class"containers"><div class"canvas" ref"canvas"></div&g…...
python通过正则匹配SQL
pattern r"(?:[^;]|(?:\\.|[^])*);" sql_list [match.group().strip() for match in re.finditer(pattern, execute_sql) if match.group().strip()]for sql in sql_list:print(sql)(?:[^;]|(?:\\.|[^])*); 匹配 连续的非分号内容 或 单引号包裹的字符串&#…...
设置首选网络类型以及调用Android框架层的隐藏API
在Android SDK中提供的framework.jar是阉割版本的,比如有些类标记为hide,这些类不会被打包到这个jar中,而有些只是类中的某个方法或或属性被标记为hide,则这些类或属性会被打包到framework.jar,但是我们无法调用&#…...
观察者模式和发布-订阅模式有什么异同?它们在哪些情况下会被使用?
大家好,我是锋哥。今天分享关于【观察者模式和发布-订阅模式有什么异同?它们在哪些情况下会被使用?】面试题。希望对大家有帮助; 观察者模式和发布-订阅模式有什么异同?它们在哪些情况下会被使用? 1000道 …...
如何保证mysql数据库到ES的数据一致性
1.同步双写方案 在代码中对数据库和ES进行双写操作,确保先更新数据后更新ES。 优点: 数据一致性:双写策略可以保证在MySql和Elasticsearch之间数据的强一致性,因为每次数据库的变更都会在Elasticsearch同步反映。实时性…...
RabbitMQ 的7种工作模式
RabbitMQ 共提供了7种⼯作模式,进⾏消息传递,. 官⽅⽂档:RabbitMQ Tutorials | RabbitMQ 1.Simple(简单模式) P:⽣产者,也就是要发送消息的程序 C:消费者,消息的接收者 Queue:消息队列,图中⻩⾊背景部分.类似⼀个邮箱,可以缓存消息;⽣产者向其中投递消息,消费者从其中取出消息…...
红黑树 Red-Black Tree介绍
1. 红黑树的定义 红黑树是一种具有如下性质的二叉搜索树: 每个节点是红色或黑色。根节点是黑色。所有叶子节点都是黑色的空节点(NIL节点),即哨兵节点。如果一个节点是红色,那么它的子节点一定是黑色。(不存…...
我的创作纪念日—致敬未来的自己
机缘 为什么想去写文章呢? 1、想把自己学的知识和技能做一个总结。 2、想给多年后的自己留下一些财富。 3、希望自己分享的知识和经验也能帮到其他有需要的人 收获 在创作的过程中都有哪些收获? 1、每次对知识的总结,都让我的技能更加的…...
Android Studio IDE环境配置
需要安装哪些东西: Java jdk Java Downloads | OracleAndroid Studio 下载 Android Studio 和应用工具 - Android 开发者 | Android DevelopersAndroid Sdk 现在的Android Studio版本安装时会自动安装,需要注意下安装的路径Android Studio插件…...
matlab中的cell
在MATLAB中,cell 是一种非常重要的数据类型,它能够存储不同类型和大小的数据,这使得它非常灵活,适用于处理复杂的数据结构。 1. 基本介绍 cell 类型的变量可以存储不同类型的数据,如数值、字符、结构体、甚至其他的 …...
Vue项目中env文件的作用和配置
在实际项目的开发中,我们一般会经历项目的开发阶段、测试阶段和最终上线阶段,每一个阶段对于项目代码的要求可能都不尽相同,那么我们如何能够游刃有余的在不同阶段下使我们的项目呈现不同的效果,使用不同的功能呢?这里…...
基于致远OA+慧集通平台的企业主数据管理设计方案(一)
目标 1、实现集团组织主数据的集中统一管理,包括到主数据在致远中的审批新增、编辑、分发等操作; 2、实现集团用户系统权限的集中管理,统一在致远平台中为用户配置各系统中的权限,配置完成后,可以自动或手动的分发到…...
vue前端实现同步发送请求,可设置并发数量【已封装】
新建 TaskManager.js export default class TaskManager {constructor(maxConcurrentTasks 1) {// 最大并发任务数// to do// 并发任务数大于1 接口开始有概率返回空值,推测是后端问题this.maxConcurrentTasks maxConcurrentTasks;this.currentTasks 0;this.tas…...
vue3使用vant日历组件(calendar),自定义日历下标的两种方法
在vue3中使用vant日历组件(calendar)自定义下标的两种方法,推荐使用第二种: 日期下方加小圆点: 一、使用伪元素样式实现(::after伪元素小圆点样式会被覆盖,只能添加一个小圆点) 代码如下(示例…...
Java线程池面试题
为什么要用线程池 降低资源消耗:通过重复利用已创建的线程降低线程创建和销毁造成的消耗提高响应速度:当任务到达时,任务可以不需要等到线程创建就能立即执行方便管理线程:线程是稀缺资源,如果无条件地创建࿰…...
我的 2024 年终总结
2024 年,我离开了待了两年的互联网公司,来到了一家聚焦教育机器人和激光切割机的公司,没错,是一家硬件公司,从未接触过的领域,但这还不是我今年最重要的里程碑事件 5 月份的时候,正式提出了离职…...
Mysql8 数据库安装及主从配置
一、MySQL8 安装 下载 MySQL 8 的安装包并将其上传到服务器。将安装包解压到指定的目录,例如 /opt/mysql8。创建一个名为 mysql 的用户组和一个名为 mysql 的用户,并将用户添加到组中。同时,设置用户密码并更改用户的主目录和默认 shell。配…...
Unity中UGUI的Button动态绑定引用问题
Unity中UGUI的Button动态绑定引用问题 问题代码修改代码如下总结 问题代码 Button动态绑定几个连续的按钮事件时使用for循环的i做按钮的id发现按钮点击对应不上。如下代码 for (int i 0; i < 10; i) {btn[i].onClick.AddListener(() >{Click(i);}); }/// <summary&…...
测试基础之测试分类
软件测试是确保软件产品满足预期功能、性能和用户体验要求的关键环节。它的主要目的是通过系统化的方法发现并修复软件中的缺陷,从而提高软件的质量和可靠性。在软件开发生命周期的不同阶段执行测试,以尽早发现潜在的错误或类型,早期发现缺陷…...
VS2022 中的 /MT /MTd /MD /MDd 选项
我们有时编译时,需要配置这个 运行库,指定C/C++运行时库的链接方式。 如下图 那么这些选项的含义是什么? /MT:静态链接多线程库 /MT选项代表“Multi-threaded Static”,即多线程静态库。选择此选项时,编译器会从运行时库中选择多线程静态连接库来解释程序中的代码,…...
socket.io
import { ref } from "vue" import io from "socket.io-client" import { getToken } from "./auth" const socket ref(null) const serverUri import.meta.env.VITE_APP_API_URL// 你的服务器地址 // const serverUri "http://172.16.3…...
latex常见问题汇总
文章目录 单行多图显示双栏插入图片 单行多图显示 \begin{figure}[t!] % case 1\centering\setlength{\tabcolsep}{0.5pt} % 图片之间的距离为0.5 point\begin{tabular}{ccc}\includegraphics[width0.30\linewidth, height0.33\linewidth]{pic/xuLun/thin.png} &\includeg…...
从数据到决策:如何利用多维度交叉分析提升企业整体效能
随着“GenAI”技术的崛起,数据分析在各行各业的应用也发生了深远的变化。IDC中国的调研数据显示,68%的企业在落地GenAI应用时认为,梳理和整合内部数据资产是首要任务;66%的企业则表示,搭建数据湖等数据底座是推动智能化…...
Nmap基础入门及常用命令汇总
Nmap基础入门 免责声明:本文单纯分享技术,请大家使用过程中遵守法律法规~ 介绍及安装 nmap是网络扫描和主机检测的工具。作为一个渗透测试人员,必不可少的就是获取信息。那么nmap就是我们从互联网上获取信息的途径,我们可以扫描互…...
【gopher的java学习笔记】spring web接口404了怎么办
今天新搭了一个spring boot带spring web的工程,不得不说,这java的生态是比golang要齐全一点,各种脚手架工程应有尽有。 因为我们的目标是有个web service,所以spring boot的工程搭好之后,就寻思着给这个spring应用添加…...
constexpr 的概念及用途
constexpr 的概念及用途 constexpr 是 C11 引入的关键字,用于定义常量表达式。常量表达式是指在编译时能够求值的表达式,也就是说,constexpr 用来标识那些编译器在编译时就可以计算结果的变量、函数或对象。 constexpr 在 C 中非常重要&…...
开放世界目标检测 Grounding DINO
开放世界目标检测 Grounding DINO flyfish Grounding DINO 是一种开创性的开放集对象检测器,它通过结合基于Transformer的检测器DINO与基于文本描述的预训练技术,实现了可以根据人类输入(如类别名称或指代表达)检测任意对象的功…...
【Spring】基于XML的Spring容器配置—— <import>标签的使用
Spring容器是Spring框架的核心部分,负责管理应用程序中的对象及其生命周期。Spring容器的配置方式有多种,其中基于XML的配置方式仍然被广泛使用,尤其是在一些老旧项目中。本文将详细介绍Spring容器配置中的<import>标签的使用ÿ…...
GemPy 3 地质建模快速入门指南
GemPy 3简介 GemPy 3是一款基于Python的开源三维结构地质建模软件。 GemPy 3由德国的Terranigma Solutions公司维护,并在GitHub上进行开源开发。它允许用户从界面和方向数据中自动创建复杂的地质模型,并支持随机建模以解决参数和模型不确定性问题。新版…...
智慧农业物联网传感器:开启农业新时代
在当今科技飞速发展的时代,农业领域正经历着一场前所未有的变革,而智慧农业物联网传感器无疑是这场变革中的关键利器。它宛如农业的 “智慧大脑”,悄然渗透到农业生产的各个环节,为传统农业注入了全新的活力,让农业生产…...
Spring Boot应用开发实战:从入门到精通
一、Spring Boot 简介 1.1 什么是 Spring Boot? Spring Boot 是一个开源框架,旨在简化新 Spring 应用的初始搭建以及开发过程。它构建在 Spring 框架之上,利用了 Spring 的核心特性,如依赖注入(Dependency Injection&…...
salesforce Controlled by Parent 的对象如何实现部分情况 Parent可见,但是 该对象不可见
在 Salesforce 中,设置对象的访问控制为“Controlled by Parent”时,该对象的可见性通常由其主对象(Parent)的共享规则或权限决定。如果主对象可见,子对象也会自动继承可见性。然而,有时候我们希望实现一些…...
React 第二十节 useRef 用途使用技巧注意事项详解
简述 useRef 用于操作不需要在视图上渲染的属性数据,用于访问真实的DOM节点,或者React组件的实例对象,允许直接操作DOM元素或者是组件; 写法 const inpRef useRef(params)参数: useRef(params),接收的 …...
TCP/IP 邮件
TCP/IP邮件是互联网通信中非常重要的应用之一。当我们发送电子邮件时,我们实际上并没有直接使用TCP/IP协议,而是通过电子邮件程序,例如微软的Outlook、莲花软件的Notes或Netscape Communicator等来实现。这些电子邮件程序背后使用了不同的TCP…...
前缀和与差分
目录 前缀和 一维前缀和 二维前缀和 差分 一维差分 二维差分 进阶练习NOIP普及组与提高组 前缀和 前缀和是一种思想,代码短小精悍是它的特点。相比于数据较大时的从头至尾遍历和优化过的双指针方法来求区间和,前缀和在对于数据进行处理的速度上有…...