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;
}

 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号