Contêiner de conjunto C++
O conceito de container set/multiset
Recursos: Todos os elementos serão classificados automaticamente quando inseridos.
Essência: conjunto/multiconjunto é um contêiner associativo e a estrutura subjacente é implementada com uma árvore binária
A diferença entre set e multiset:
set não permite elementos repetidos no container
multiset permite elementos repetidos no container
Observação: os arquivos de cabeçalho precisam ser incluídos ao usar contêineres de conjunto ou multiconjunto
#include<set>
1. A construção e atribuição do conjunto
Construção:
set<T> st;
//Construção padrão
set(const set& st);
//Copiar construção
Atribuição:
set& operator=(const set& st);
Operador de atribuição de sobrecarga
Antes de testar, primeiro criamos uma função de impressão, que é frequentemente usada em testes
void printSet(const set<int>& st)
{
cout << "打印set容器:" ;
for (set<int>::iterator it = st.begin(); it != st.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
Caso de teste:
void text()
{
set<int> s1; //默认构造
//set插入数据只有insert的方式
s1.insert(20);
s1.insert(30);
s1.insert(10);
//s1.insert(10); //容器中已经有相同的元素,插入失败,但并不报错
//打印s1,是按升序排序好的顺序打印的
printSet(s1);
set<int> s2(s1); //拷贝构造
set<int> s3;
s3 = s1; //重载的赋值运算符
}
Resultado dos testes:
2. definir tamanho e troca
Protótipo da função:
size();
//Retorna o número de elementos no contêiner
empty();
//Julga se o contêiner está vazio, retorna 1 se estiver vazio, caso contrário, retorna 0
swap();
//Troca dois contêineres
Caso de teste:
void text()
{
set<int> s1, s2;
//empty()
if (s1.empty()) //如果s1为空
{
s1.insert(1);
s1.insert(5);
s1.insert(3);
}
if (s2.empty())
{
s2.insert(10);
s2.insert(50);
s2.insert(30);
s2.insert(80);
}
//size()
cout << "s1的大小为:" << s1.size() << endl;
cout << "s2的大小为:" << s2.size() << endl;
//swap()
cout << "交换前:" << endl;
printSet(s1);
printSet(s2);
s1.swap(s2);//交换s1和s2
cout << "交换后:" << endl;
printSet(s1);
printSet(s2);
}
Resultado dos testes:
3. definir inserção e exclusão
Protótipo da função:
insert();
//Inserir um elemento no contêiner
erase(pos);
//Excluir o elemento apontado pelo iterador pos, retornar o iterador do próximo elemento
erase(elem);
//Excluir o elemento cujo valor é elem no contêiner
erase(begin,end);
//Excluir o intervalo do iterador é [ beg,end) Todos os elementos no container retornam um iterador para o próximo elemento
clear();
//Esvazia todos os elementos no container
Caso de teste:
void text()
{
set<int> s;
//insert()
s.insert(10);
s.insert(8);
s.insert(15);
s.insert(2);
printSet(s);
//erase()
s.erase(s.begin()); //删除首个元素,由于set容器插入时已经升序排序好了,此时删除的是最小的元素
printSet(s);
s.erase(10); //删除为10的元素
printSet(s);
//清空
s.clear(); //等价于s.erase(s.begin(),s.end());
printSet(s);
}
Resultado dos testes:
4. Defina a pesquisa e as estatísticas
Protótipo da função:
find(elem);
//Encontre a posição do elem no container, se houver um iterador para elem retornar o elemento, return set.end() se não houver elem; // O
count(elem);
número de elementos elem no container a serem contado, o número de elementos no contêiner definido pode ser apenas 0 ou 1, o contêiner multiconjunto pode ser maior que 1
Caso de teste:
void text()
{
set<int> s;
s.insert(5);
s.insert(3);
s.insert(4);
s.insert(2);
printSet(s);
//find()
set<int>::iterator pos = s.find(5);
if (pos != s.end())
{
cout << "找到元素:" << *pos << endl;
}
else cout << "没有该元素" << endl;
//count()
cout << "元素5" << "有" << s.count(5) << "个" << endl;
}
Resultado dos testes:
5. A diferença entre set e multiset
a diferença:
- set não permite inserir os mesmos dados, enquanto multiset permite
- Quando set insere dados, ele retornará o resultado da inserção, indicando se a inserção foi bem-sucedida, e o resultado é recebido pelo par
- multiset não detectará dados, então os mesmos dados podem ser inseridos
O par de grupos será apresentado em detalhes abaixo, agora use-o primeiro
Caso de teste:
void text()
{
set<int> s;
//用pair接收s的插入结果
pair < set<int>::iterator, bool > ret = s.insert(10);
if (ret.second)//ret的第二个类型数据,即bool类型,若为真则插入成功
{
cout << "插入成功" << endl;
}
else cout << "插入失败" << endl;
ret = s.insert(10);
if (ret.second)//ret的第二个类型数据,即bool类型,若为真则插入成功
{
cout << "插入成功" << endl;
}
else cout << "插入失败" << endl;
//multiset可以重复插入相同元素,不检测插入结果
multiset<int> ms;
ms.insert(10);
ms.insert(10);
ms.insert(10);
cout << "打印multiset容器:";
for (multiset<int>::iterator it = ms.begin(); it != ms.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
Resultado dos testes:
6. criação de grupos de pares
O conceito de pares: dados que ocorrem em pares
Duas formas de criar:
pair<T1,T2> p(value1,value2);
pair<T1,T2> p = make_pair(value1,value2);
use:
p.first;
//retorna o primeiro tipo de dado do par
p.second;
//retorna o segundo tipo de dado do par
Vale ressaltar que o uso do par não requer um arquivo de cabeçalho
Caso de teste:
void text()
{
//创建
pair<string, int> p1("张三", 25);
pair<string, int> p2 = make_pair("李四", 30);
//使用
cout << "姓名:" << p1.first << " 年龄:" << p1.second << endl;
cout << "姓名:" << p2.first << " 年龄:" << p2.second << endl;
}
Resultado dos testes:
7. defina o agrupamento do contêiner
Já sabemos que ao inserirmos os dados, o container definido irá nos ordenar automaticamente, por padrão, ele é ordenado do menor para o maior, ou seja, em ordem crescente.
Você deve estar se perguntando:
- Você pode alterar as regras de classificação para classificar em ordem decrescente?
- Defina uma classe que tenha várias variáveis de membro, então como classificamos por cada membro?
Para os dois casos acima, geralmente introduzimos functors, personalizamos uma regra de classificação e como classificar depende de nós
Caso de teste: classificando tipos de dados integrados
class Mycompare
{
public:
bool operator()(int v1,int v2) const //重载() 运算符
{
return v1 > v2; //指定排序规则,从大到小,也就是降序排序
}
};
void text1()
{
set<int,Mycompare> s1;
s1.insert(10);
s1.insert(50);
s1.insert(30);
s1.insert(40);
cout << "打印降序排序的set容器:" << endl;
for (set<int, Mycompare>::iterator it = s1.begin(); it != s1.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
Resultado dos testes:
Caso de teste: classificação de tipos de dados personalizados
class Person
{
public:
string m_name;
int m_age;
Person(string name, int age) :m_name(name), m_age(age) {
}
};
class Mycompare
{
public:
bool operator()(const Person& p1,const Person& p2) const //重载() 运算符
{
return p1.m_age > p2.m_age;
}
};
void text1()
{
set<Person,Mycompare> s1;
Person p1("张三", 25);
Person p2("李四", 20);
Person p3("王五", 30);
s1.insert(p1);
s1.insert(p2);
s1.insert(p3);
cout << "按照年龄大小降序排序:" << endl;
for (set<Person, Mycompare>::iterator it = s1.begin(); it != s1.end(); it++)
{
cout << "姓名:" << (*it).m_name << " 年龄:" << (*it).m_age << endl;
}
}
Resultado dos testes: