set/multiset容器

set/multiset容器

头文件:#include <set>

1. set 基本概念

  • 所有元素都会在插入时自动被排序
  • set/multiset属于关联式容器,底层结构是用二叉树实现。

set和multiset区别

  • set不允许容器中有重复的元素
  • multiset允许容器中有重复的元素

2. set 构造和赋值

构造:

  • set<T> st; //默认构造函数:
  • set(const set &st); //拷贝构造函数

赋值:

  • set& operator=(const set &st); //重载等号操作符

示例:

    set<int> s1;  
    s1.insert(10); 
    
    //拷贝构造  
    set<int>s2(s1);  
    printSet(s2);  
    
    //赋值  
    set<int>s3;  
    s3 = s2;     // 输出的值和s1一致

3. set 插入和删除

函数原型:

  • insert(elem); //在容器中插入元素。
  • clear(); //清除所有元素
  • erase(pos); //删除 pos 迭代器所指的元素,返回下一个元素的迭代器。
  • erase(beg, end); //删除区间[beg,end)的所有元素 ,返回下一个元素的迭代器。
  • erase(elem); //删除容器中值为 elem 的元素。

示例:

    for (set<int>::iterator it = s.begin(); it != s.end(); it++)  
    {  
        cout << *it << " ";  
    }  

    set<int> s1;  
    //插入  
    s1.insert(10);  
​  
    //删除  
    s1.erase(s1.begin());  
    //  s1.erase(s1.begin() + 1);    // 这是错误的
    // 使用迭代器
    set<int>::iteration it = s1.begin();
	s1.erase(++it); 
	
    s1.erase(s1.begin(), s1.end());
    s1.erase(10);     // 如不存在,不删除
    
    //清空  
    s1.clear();    

4. set 大小和交换

函数原型:

  • size(); //返回容器中元素的数目
  • empty(); //判断容器是否为空
  • swap(st); //交换两个集合容器

示例:

s1.swap(s2);  
s1.size();
s1.empty();

5. set 查找和统计

函数原型:

  • find(key); //查找 key 是否存在,若存在,返回该键的元素的迭代器;若不存在,返回 set.end();
  • count(key); //统计key的元素个数

示例:

s1.count(30);
if(s1.find(30)!=s1.end())
	cout << "找到";

// 同理,if(s1.find(30) != s1.end() - 1)是错误的
// 但是可以使用迭代器

总结:

  • 查找 --- find (返回的是迭代器)
  • 统计 --- count (对于set,结果为0或者1)

6. set 和 multiset 区别

区别:

  • set不可以插入重复数据,而multiset可以
  • set插入数据的同时会返回插入结果,表示插入是否成功
  • multiset不会检测数据,因此可以插入重复数据

总结:

  • 如果不允许插入重复数据可以利用set
  • 如果需要插入重复数据利用multiset

7. set 容器的排序

  • set 容器默认排序规则为从小到大,利用仿函数,可以改变排序规则
  • 分为内置数据类型排序和自定义数据类型排序
  • 自定义的数据类型就不方便了,自定义排序,完全可以使用结构体排序了
#include <iostream>
#include <string>
#include <set>
using namespace std;

// 可以
struct intComp {
	bool operator () (const int& lhs, const int& rhs) const {
		return lhs > rhs;
	}
};

// 也可以
class Mycompare
{
public:
	bool operator () (const int& lhs, const int& rhs) const {
		return lhs > rhs;
	}
};

// 不可以
bool cmp(int a, int b)
{
	return a > b;
}

struct strComp
{
	bool operator () (const string& str1, const string& str2) const {
		return str1.length() < str2.length();
	}
};

int main()
{
	int a[] = { 10, 20, 30, 40, 50 };
	//set<int, intComp> s1(a, a + 5);
	// set<int, cmp> s1(a, a + 5);   不可以
	set<int, Mycompare> s1(a, a + 5);
	for (auto it = s1.cbegin(); it != s1.cend(); it++)
	{
		cout << *it << " ";
	}
	cout << endl;

	string b[] = { "apple", "banana", "pear", "orange", "strawberry" };
	set<string, strComp > s2 (b, b + 5);
	for (auto it = s2.cbegin(); it != s2.cend(); it++)
	{
		cout << *it << " ";
	}
	cout << endl;
	system("pause");
	return 0;
}

输出

50 40 30 20 10
pear apple banana strawberry

自定义数据类型排序

#include <iostream>
#include <string>
#include <set>
using namespace std;

struct person
{
    string name;
    int age;

    person(string name, int age)
    {
        this->name = name;
        this->age = age;
    }

    // 定义 < 操作符
    bool operator<(const person& p) const
    {
        return this->age < p.age;
    }
};

int main()
{
    set<person> s;

    // 插入数据
    s.insert(person("Alice", 30));
    s.insert(person("Bob", 25));
    s.insert(person("Charlie", 35));
    s.insert(person("Alice", 30)); // 不会被插入,因为已经存在

    // 输出数据
    for (const auto& p : s)
    {
        cout << "Name: " << p.name << ", Age: " << p.age << endl;
    }

    return 0;
}
posted @ 2024-03-15 17:19  星竹z  阅读(5)  评论(0编辑  收藏  举报