C++进阶 —— set

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

目录

一,set介绍

二,set成员函数

三,set应用


一,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
}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值