目录
一,set介绍
- set是一个有序的、不重复的关联式容器;
- 元素会自动排序,默认升序(小于比较),即无论插入顺序如何都会自动维护元素顺序;
- 内部比较对象(compare)决定了元素的排序和唯一性判断,按特定严格弱排序准则进行排序;
- 使用set的迭代器遍历元素(迭代器中序),可得到有序序列;
- 元素不可修改(元素总是const),但可快速查找、插入和删除元素;
- 查找、插入、删除时间复杂度:O(log n);
- 访问元素比unordered_set容器慢,但永许根据顺序对子集进行直接迭代;
- 主要应用于自动维护数据有序性,快速检查元素是否存在,保证元素唯一性(去重),进行集合运算(并集、交集、差集),需按顺序遍历元素;
- set在底层逻辑上是用二叉搜索树(红黑树)实现的;
// set
插入时必须检查是否存在,返回 (iterator, bool);
// multiset
插入时不需要检查,返回 iterator;
注,底层元素存储结构:
- map/multimap中存储的是真正的键值对,set中只存放key;
- set中插入元素时,只需要插入key即可,不需要构成键值对;
// 红黑树节点只存储key struct Node { Key key; // 只存储键 Node* left; Node* right; Node* parent; bool color; };
注,严格弱序(Strict Weak Ordering):
非自反性,任何元素不能小于自身:a<a 错误;
非对称性,如a小于b,则b不能小于a:如a<b,b<a 错误;
可传递性:如a<b,b<c,那么a<c;
等价传递性:如a=b,b=c,那么a=c;
二,set成员函数

key_type/value_type即为T; key_compare/value_compare即为Compare;
构造函数

操作函数
//迭代器
iterator begin() noexcept;
const_iterator begin() const noexcept;
iterator end() noexcept;
const_iterator end() const noexcept;
reverse_iterator rbegin() noexcept;
const_reverse_iterator rbegin() const noexcept;
reverse_iterator rend() noexcept;
const_reverse_iterator rend() const noexcept;
//插入
single element (1)
pair<iterator,bool> insert (const value_type& val);
pair<iterator,bool> insert (value_type&& val);
with hint (2)
iterator insert (const_iterator position, const value_type& val);
iterator insert (const_iterator position, value_type&& val);
range (3)
template <class InputIterator>
void insert (InputIterator first, InputIterator last);
initializer list (4)
void insert (initializer_list<value_type> il);
//删除
iterator erase (const_iterator position);
size_type erase (const value_type& val);
iterator erase (const_iterator first, const_iterator last);
//查找
const_iterator find (const value_type& val) const;
iterator find (const value_type& val);
bool empty() const noexcept;
size_type size() const noexcept;
size_type count (const value_type& val) const;
void swap (set& x);
void clear() noexcept;
key_compare key_comp() const;
value_compare value_comp() const;
iterator lower_bound (const value_type& val);
const_iterator lower_bound (const value_type& val) const;
iterator upper_bound (const value_type& val);
const_iterator upper_bound (const value_type& val) const;
pair<const_iterator,const_iterator> equal_range (const value_type& val) const;
pair<iterator,iterator> equal_range (const value_type& val);
int main()
{
int arr[] = { 5,3,4,1,7,8,2,6,0,9,1,5 };
int sz = sizeof(arr) / sizeof(int);
set<int> s(arr, arr + sz);
cout << s.size() << endl;
s.insert(10);
s.erase(1);
for (auto& e : s)
{
cout << e << " "; //可去重
}
cout << endl;
for (auto it = s.rbegin(); it != s.rend(); ++it)
{
cout << *it << " ";
}
cout << endl;
cout << s.count(1) << endl;
s.empty();
s.clear();
return 0;
}
三,set应用
// 去除重复元素
void removeDuplicates() {
vector<int> data = { 1, 2, 2, 3, 3, 3, 4, 2, 1, 5 };
// 一行代码完成去重
set<int> uniqueData(data.begin(), data.end());
cout << "原始数据: ";
for (int n : data) cout << n << " ";
cout << "\n去重后: ";
for (int n : uniqueData) cout << n << " ";
// 输出: 1 2 3 4 5
}
// 用户权限存在性检查
class AccessControl {
private:
set<string> adminUsers = { "alice", "bob", "charlie" };
set<string> bannedIPs = { "192.168.1.100", "10.0.0.5" };
public:
void addAdmin(const string& username) {
adminUsers.insert(username);
}
bool isAdmin(const string& username) {
return adminUsers.find(username) != adminUsers.end();
}
bool isIPBanned(const string& ip) {
return bannedIPs.find(ip) != bannedIPs.end();
}
};
// 使用示例
void checkAccess() {
AccessControl ac;
cout << "Alice是管理员: " << ac.isAdmin("alice") << endl; // true
cout << "Eve是管理员: " << ac.isAdmin("eve") << endl; // false
}
// 自动排序 - 维护有序数据,排行榜系统
class Leaderboard {
private:
set<int> scores; // 自动按升序排列
public:
void addScore(int score) { scores.insert(score); }
void showTopScores(int count) {
cout << "最高分: ";
// 使用反向迭代器从大到小遍历
auto it = scores.rbegin();
for (int i = 0; i < count && it != scores.rend(); ++i, ++it) {
cout << *it << " ";
}
cout << endl;
}
int getHighestScore() {
return *scores.rbegin(); // 最后一个元素是最大值
}
};
void testLeaderboard() {
Leaderboard lb;
lb.addScore(85);
lb.addScore(92);
lb.addScore(78);
lb.addScore(92); // 重复分数,不会插入
lb.showTopScores(3); // 输出: 92 85 78
}
// 集合运算
void setOperations() {
set<int> A = { 1, 2, 3, 4, 5 };
set<int> B = { 4, 5, 6, 7, 8 };
// 并集
set<int> unionSet;
set_union(A.begin(), A.end(), B.begin(), B.end(),
inserter(unionSet, unionSet.begin()));
// 交集
set<int> intersectionSet;
set_intersection(A.begin(), A.end(), B.begin(), B.end(),
inserter(intersectionSet, intersectionSet.begin()));
// 差集 A - B
set<int> differenceSet;
set_difference(A.begin(), A.end(), B.begin(), B.end(),
inserter(differenceSet, differenceSet.begin()));
cout << "并集: ";
for (int n : unionSet) cout << n << " "; // 1 2 3 4 5 6 7 8
cout << "\n交集: ";
for (int n : intersectionSet) cout << n << " "; // 4 5
cout << "\n差集A-B: ";
for (int n : differenceSet) cout << n << " "; // 1 2 3
}

文章介绍了C++标准库中的set容器,它是一个存储唯一元素并按特定排序规则排列的集合。set基于红黑树实现,提供快速插入、删除和查找操作。文章详细列举了set的主要构造函数和操作函数,包括迭代器、插入元素、删除元素、查找元素的方法,并给出了一个简单的示例展示如何使用set进行元素的插入、删除、遍历和查找等操作。

7189

被折叠的 条评论
为什么被折叠?



