临海企业网站建设公司,做网站开发用哪种语言好,手机排版软件app,wordpress 商品模板下载一. 容器分类#xff1a;序列式容器与关联式容器的本质区别
STL 容器的设计围绕 “数据如何存储与访问” 展开#xff0c;序列式与关联式容器的核心差异体现在存储逻辑与访问方式上#xff0c;具体对比如下#xff1a;
特性序列式容器#xff08;如 vector、list#x…一. 容器分类序列式容器与关联式容器的本质区别STL 容器的设计围绕 “数据如何存储与访问” 展开序列式与关联式容器的核心差异体现在存储逻辑与访问方式上具体对比如下特性序列式容器如 vector、list关联式容器如 set、map存储逻辑按插入顺序存储元素位置由插入时机决定按键key的内在规则存储如排序规则访问方式通过下标/迭代器位置访问如vec[2]通过键值匹配访问如set.find(3)底层结构动态数组vector、双向链表list等平衡二叉搜索树红黑树set/map、哈希表unordered_set核心优势插入顺序稳定适合频繁增删尾部元素自动排序查找/删除效率高O(log N)或O(1)典型使用场景存储连续数据、需要按插入顺序遍历、动态扩容需求去重排序、快速查找、键值映射、区间操作补充说明序列式容器强调“位置”元素的价值在于其存储的内容本身关联式容器强调“关联关系”元素的价值在于通过 key 快速定位如 “根据 ID 查找用户信息”set 作为 “key” 型关联式容器仅存储键值核心功能是 “基于 key 的排序与查找”。二. set 系列核心原理红黑树赋能的高效特性set 与 multiset 底层均基于红黑树一种自平衡二叉搜索树实现这一结构赋予它们以下核心特性自动排序红黑树的中序遍历结果为有序序列因此 set 插入元素后会自动按 key 的默认规则less升序排序无需手动调用排序函数如果需要按自己的需求比较可以自行实现仿函数传给第二个模板参数。去重与允许重复set 不允许存储重复 keymultiset 支持重复 key不可修改 keyset 的迭代器为const_iterator无法通过迭代器修改 key修改会破坏红黑树结构高效操作增删查操作的时间复杂度均为O(log N)远优于 vector 的O(N)set的声明template class T, // set::key_type/value_type class Compare lessT, // set::key_compare/value_compare class Alloc allocatorT // set::allocator_type class set;参考文档set - C Referenceset的构造相关接口// empty (1) ⽆参默认构造 explicit set (const key_compare comp key_compare(), const allocator_type alloc allocator_type()); // range (2) 迭代器区间构造 template class InputIterator set (InputIterator first, InputIterator last, const key_compare comp key_compare(), const allocator_type allocator_type()); // copy (3) 拷⻉构造 set (const set x); // initializer list (5) initializer 列表构造 set (initializer_listvalue_type il, const key_compare comp key_compare(), const allocator_type alloc allocator_type()); // 迭代器是⼀个双向迭代器 iterator - a bidirectional iterator to const value_type // 正向迭代器 iterator begin(); iterator end(); // 反向迭代器 reverse_iterator rbegin(); reverse_iterator rend();三. set 核心接口实战基于实操代码详解下面会通过多个测试函数覆盖 set 的核心操作我们结合代码解析其使用方法与注意事项。3.1 初始化与插入去重 自动排序set 支持多种插入方式插入后自动去重并按升序排列代码示例注意看注释#define _CRT_SECURE_NO_WARNINGS 1 #includeiostream #includeset using namespace std; // 测试set的插入与遍历去重自动排序 void test_set1() { setint s; // 方式1单个元素插入 //s.insert(3); //s.insert(1); //s.insert(2); //s.insert(5); //s.insert(3); //s.insert(5); //s.insert(6); // 方式2初始化列表批量插入 s.insert({ 3,1,2,5,3,5,6 }); // 遍历方式1迭代器遍历注意*it不可修改 // 遍历结果: 去重有序 setint::iterator it s.begin(); while (it ! s.end()) { //*it1 1;//不能修改 cout *it ; it; } cout endl; // 遍历方式2范围for循环 for (auto e : s) { cout e ; } cout endl; } int main() { test_set1(); return 0; }关键说明若需降序排序可指定排序仿函数setint, greaterint s。3.2 查找与删除精准操作单个元素set 提供find查找、count统计、erase删除接口支持按 key 或迭代器操作// 测试set的查找与删除 // 测试set的查找与删除 void test_set2() { setint s; s.insert({ 3,1,2,5,3,5,6 });// 去重后1 2 3 5 6 int x 0; cin x; cout s.erase(x) endl;//删掉了几个返回值就是几在set里就是1没删掉就是0 //查找元素find返回迭代器未找到则返回s.end() //auto pos s.find(x); //if (pos ! s.end()) //{ // s.erase(pos);//找到后删除 //} // 统计元素个数set中仅返回0或1判断存在性 if (s.count(x)) { } for (auto e : s) { cout e ; } cout endl; } int main() { test_set2(); return 0; }关键说明erase的返回值是删除元素的个数在set里要么是0要么是1multiset删了几个就是几count在 set 中主要用于判断元素是否存在在 multiset 中返回实际个数。3.3 区间操作lower_bound 与 upper_boundset 的区间操作依赖lower_bound和upper_bound用于快速定位边界结合erase可高效删除区间元素// 测试set的区间操作 void test_set3() { setint s; s.insert({ 3,1,2,5,3,5,6,7,9}); for (auto e : s) { cout e ; } cout endl; // 需求删除[3, 8]区间的元素即3且8 // lower_bound(val)返回第一个val的迭代器此处指向3 auto it1 s.lower_bound(3); // upper_bound(val)返回第一个val的迭代器此处指向9 auto it2 s.upper_bound(8); // 按迭代器区间删除删除[it1, it2)内的元素 s.erase(it1, it2); for (auto e : s) { cout e ; } cout endl; } int main() { test_set3(); }关键说明lower_bound与upper_bound的时间复杂度均为O(log N)是区间操作的核心区间[it1, it2)为“左闭右开”这样符合 STL 迭代器区间的通用设计如[begin, end)。四. multiset支持重复 key 的关联式容器multiset 与 set 接口一致核心差异是允许重复 key适用于需要存储相同元素并统计频率的场景// 测试multiset支持重复key void test_multiset() { multisetint s; // 插入重复元素不会去重 s.insert({ 3,1,2,5,3,5,6,3,3 }); // 1. 遍历有序但保留重复元素 multisetint::iterator it s.begin(); while (it ! s.end()) { //*it 1;//不能修改 cout *it ; it; } cout endl; // 2. 查找返回中序遍历的第一个目标元素 auto pos s.find(3); //打印所有3 while (pos ! s.end() *pos 3) { cout *pos ; pos; } cout endl; // 3.查找有3的区间左闭右开,【) //std::pairmultisetint::iterator, multisetint::iterator ret s.equal_range(3); auto ret s.equal_range(3); // 4. 统计返回元素实际个数 cout s.count(3) endl;//有几个3 // 5.删除按key删除所有匹配元素 cout s.erase(3) endl;//删掉所有的3并返回删掉的3的个数 s.erase(5);//删掉所有的5 for (auto e : s) { cout e ; } cout endl; } int main() { test_multiset(); }set 与 multiset 的核心差异总结操作setmultiset插入重复元素自动去重重复元素插入失败不去重保留所有重复元素插入成功finda(key)返回唯一匹配元素的迭代器未找到返回end()返回中序遍历中第一个匹配元素的迭代器count(key)返回 0 或 1仅用于判断元素是否存在返回元素在容器中实际出现的次数erase(key)若元素存在则删除 1 个不存在则删除 0 个删除容器中所有与key匹配的元素五. set 系列的实战价值解决实际开发问题set 系列的 “自动排序 高效查找” 特性在算法与工程中应用广泛以下是两个典型题目5.1环形链表 II题目链接142. 环形链表 II - 力扣LeetCode题目要求找到环形链表的入口结点思路用 set 存储遍历过的节点若插入节点时发现已存在该节点即为入口。C算法代码class Solution { public: ListNode *detectCycle(ListNode *head) { setListNode* s; ListNode* cur head; while(cur) { auto rets.find(cur); // 不存在就插入节点 if(rets.end()) s.insert(cur); // 已经存在证明这就是入环节点 else return cur; curcur-next; } return nullptr; } };5.2 两个数组的交集扩展差集思路题目链接349. 两个数组的交集 - 力扣LeetCode题目要求给定两个数组计算它们的交集结果需去重。思路用 set 对两个数组去重 排序再用双指针遍历两个 set找到共同元素。C算法代码class Solution { public: vectorint intersection(vectorint nums1, vectorint nums2) { vectorint ret; // 1. 用set对两个数组去重排序 setint s1(nums1.begin(),nums1.end()); setint s2(nums2.begin(),nums2.end()); auto it1s1.begin(); auto it2s2.begin(); // 2. 双指针遍历找共同元素 while(it1!s1.end()it2!s2.end()) { //小的 if(*it1*it2) it1; else if(*it1*it2) it2; //相等的是交集加入结果然后同时 else { ret.push_back(*it1); it1; it2; } } return ret; } };差集和交集的实战使用多端文件同步的逻辑通过“差集识别新增 / 缺失文件交集比对时间戳确定更新方向”避免全量传输大幅减少带宽消耗和同步时间是云存储、多端协作工具如网盘、协同办公软件的常见底层逻辑之一。