STL之set(集合)详解

STL之set(集合)详解

  • 一、基本概念
  • 二、常用函数
    • 2.1、构造/析构函数
      • 2.1.1、构造函数
      • 2.1.2、析构函数
      • 2.1.3、等号操作符
    • 2.2、迭代器
    • 2.3、容量
    • 2.4、元素插入、删除
    • 2.5、元素查找、操作

一、基本概念

集合是存储排序键的关联容器,其中每个键都是唯一的,可以插入或删除但不能更改。
语法:

template < class T,                             // set::key_type/value_type
           class Compare = less<T>,        // set::key_compare/value_compare
           class Alloc = allocator<T>         // set::allocator_type
           > class set;

参数
T:存储在容器集中的元素类型。
Compare:一个比较类,它接受两个具有相同bool类型的参数并返回一个值。此参数是可选的,二进制谓词less 是默认值。
Alloc:分配器对象的类型,用于定义存储分配模型。

二、常用函数

2.1、构造/析构函数

2.1.1、构造函数

set构造函数有以下五种:

  • 默认构造函数:用于构造具有零个元素的空set容器。
explicit set (const key_compare& comp = key_compare(),
              const allocator_type& alloc = allocator_type());
explicit set (const allocator_type& alloc);

// 默认构造函数
set<char> s;
int size = s.size(); 
cout << "集合s的大小 = " << size;//输出: 集合s的大小 = 0
return 0;
  • 范围构造函数:用于构造内容范围为[first,last)的容器。
template <class InputIterator>
  set (InputIterator first, InputIterator last,
       const key_compare& comp = key_compare(),
       const allocator_type& = allocator_type());	
       	
int evens[] = {
     2,4,6,8,10}; 
// 范围构造函数
set<int> myset (evens, evens+5);  
cout << "集合容器myset的大小为 : " << myset.size();//输出: 集合s的大小 = 5
  • 复制构造函数:用于构造带有现有容器元素副本的集合。
set (const set& x);
set (const set& x, const allocator_type& alloc);
//默认构造函数
std::set<int> s1;
s1.insert(5);
s1.insert(10);
// 复制构造函数
set<int> s2(s1);
cout << "\n新集合容器s2的大小为 : " << s2.size();//输出: 新集合容器s2的大小为 : 2
  • move构造函数:用于使用move语义与其他元素一起构造容器。
set (set&& x);
set (set&& x, const allocator_type& alloc);
// 默认构造函数
set<char> s1;
s1.insert('x');
s1.insert('y');
cout << "集合容器s1的大小为 : " << s1.size();//输出: 集合容器s1的大小为 : 2
// Move 构造函数
set<char> s2(move(s1));
cout << "\n新集合容器s2的大小为 : " << s2.size();//输出: 新集合容器s2的大小为 : 2
  • 初始化程序列表构造函数:用于构造带有初始化程序列表内容的集合。
set (initializer_list<value_type> il,
     const key_compare& comp = key_compare(),
     const allocator_type& alloc = allocator_type());
// 初始化列表构造函数
set<string> fruit {
     
   "orange", "apple", "mango", "peach", "grape"
};
cout << "容器内fruit的大小为 : " << fruit.size();//输出: 容器内fruit的大小为 : 5

参数
comp:比较函数对象,它接受两个关键参数,如果第一个参数在第二个参数之前,则返回true,否则返回false。默认情况下,它使用less 谓词。

alloc:一个分配器对象,用于此容器的所有内存分配。

first:将迭代器输入范围内的第一个位置。

last:将迭代器输入到范围中的最后一个位置。

x:另一个相同类型的set对象。

il:一个初始化器列表对象,将从中复制元素。

2.1.2、析构函数

~set();

2.1.3、等号操作符

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

// 默认构造函数
set<int> s1 = {
     1,2,3};
set<int> s2 = s1;//用s1来初始化s2

2.2、迭代器

  • begin()函数用于返回引用set容器的第一个元素的迭代器。
iterator begin() noexcept;   
const_iterator begin() const noexcept;
// 默认构造函数
set<char> s1;
s1.insert('x');
cout << *s1.begin();//输出:x
  • end()函数的作用是:返回一个迭代器,该迭代器位于集合的最后一个元素的下一个位置。
iterator end() noexcept; 
const_iterator end() const noexcept;
set<string> myset = {
     "Java", "C++", "SQL"};
// 显示内容:
for (set<string>::iterator it=myset.begin(); it!=myset.end(); ++it)
  cout << *it<< '\n';
  • cbegin()函数用于返回一个常量迭代器,该迭代器指向set容器的第一个元素。
  • cend()函数用于返回一个常量迭代器,该迭代器位于集合中最后一个元素的旁边。
  • rbegin()函数用于返回引用set容器的最后一个元素的反向迭代器。
    set 的反向迭代器沿相反方向移动并递增,直到到达set容器的开头(第一个元素)。
  • rend()函数用于以相反的顺序将迭代器返回到集合的末尾(不是最后一个元素,最后一个元素后面的位置)。这类似于非反转容器的第一个元素之前的元素。
  • crbegin()函数用于返回一个常量反向迭代器,该迭代器引用set容器中的最后一个元素。
    set的常量反向迭代器沿反向移动并递增,直到到达set容器的开头(第一个元素)并指向常量元素。
  • crend()函数用于以相反的顺序将常量迭代器返回到集合的末尾(最后一个元素之后的元素)。这类似于非反转容器的第一个元素之前的元素。

2.3、容量

  • empty()函数的作用是:检查集合容器是否为空。如果集合容器为空(size为0),则返回true,否则返回false。
bool empty() const;      
bool empty const noexcept; 
set<int> numbers;
cout << " 最初,numbers.empty (): " << numbers.empty() << "\n";//输出true
numbers = {
     100, 200, 300};
cout << "\n 添加元素之后,numbers.empty(): " << numbers.empty() << "\n";//输出false
  • size()函数用于查找set容器中存在的元素数。
size_type size() const; 
size_type size() const noexcept;
set<char> num {
     'a', 'b', 'c', 'd'}; 
cout << "num集合包含 " << num.size() << " 元素.\n";//输出:num集合包含 4 元素.
  • max_size()函数用于获取设置的容器可以容纳的最大大小数。
size_type max_size() const;   
size_type max_size() const noexcept;
set<char,char> s;
cout << "“set集合”的最大大小为" << s.max_size() << "\n";//输出: “set集合”的最大大小为268435455

2.4、元素插入、删除

  • insert()用于在集合中插入新元素。
    因为元素键在集合中是唯一的,所以插入操作首先检查给定键是否已存在于集合中,如果键存在于集合中,则不会将其插入到集合中并迭代到现有的迭代器返回键,否则将新元素插入集合。
//普通引用方式传参
pair<iterator,bool> insert (const value_type& val);
//右值引用方式传参
pair<iterator,bool> insert (value_type&& val);
//以普通引用的方式传递 val 值
iterator insert (const_iterator position, const value_type& val);
//以右值引用的方式传递 val 值
iterator insert (const_iterator position, value_type&& val);
template <class InputIterator>
  void insert (InputIterator first, InputIterator last);
  void insert (initializer_list<value_type> il);              

参数
val:要插入集合的值。

position:提示在元素中插入元素的位置。

first:要插入范围的起点。

last:要插入范围的末尾。

il:初始化列表。

将元素插入到集合中: 如果插入单个元素,那么复杂度将是对数的。

set<int> s;
 
// 插入元素的函数
// 在set容器中
s.insert(1);
s.insert(4);
s.insert(2);
s.insert(5);
s.insert(3);
 
cout << "集合中的元素是: ";
for (auto it = s.begin(); it != s.end(); it++)
    cout << *it << " ";
//输出:集合中的元素是: 1 2 3 4 5

将元素插入指定位置: 如果给出提示,并且给出的位置是最佳位置,则复杂度将摊销为常数。

set<int> s;
 
//插入元素的函数
//在set容器中
auto itr = s.insert(s.begin(), 1);
 
itr = s.insert(itr, 4);
itr = s.insert(itr, 2);
itr = s.insert(itr, 5);
itr = s.insert(itr, 3);
 
cout << "集合中的元素是: ";
for (auto it = s.begin(); it != s.end(); it++)
     cout << *it << " ";
//输出:集合中的元素是: 1 2 3 4 5

将给定范围内的一组元素插入到另一组:

set<int> s1;
 
//插入元素的函数
//在set容器中
s1.insert(1);
s1.insert(4);
s1.insert(2);
s1.insert(5);
s1.insert(3);
 
cout << "set1中的元素是: ";
for (auto it = s1.begin(); it != s1.end(); it++)
    cout << *it << " ";
 
set<int> s2;
 
//函数将一个集合插入到另一个集合
//从3到结束的所有元素是
//插入set2
s2.insert(s1.find(3), s1.end());
 
cout << "\nset2中的元素是: ";
for (auto it = s2.begin(); it != s2.end(); it++)
    cout << *it << " ";
//输出:set1中的元素是: 1 2 3 4 5
//	   set2中的元素是: 3 4 5

从初始化列表中插入元素:

set<string> m = {
     "Java", "C++", "SQL"};
   
// 插入初始化器列表中的元素
m.insert({
     "VB", "Oracle"});

cout << "集合包含以下元素:" << endl;

for (auto it = m.begin(); it != m.end(); ++it)
   cout << *it;
//输出:集合包含以下元素:C++ Java Oracle SQL VB
  • erase()函数用于从set容器中删除与给定键关联的单个元素或元素范围([first,last))。因此,将通过删除元素的数量来减小大小。
iterator  erase (const_iterator position);	

size_type erase (const value_type& val);	

iterator  erase (const_iterator first, const_iterator last);

参数
position:迭代器,指向要从集合中删除的单个元素。

val:要从集合中删除的值。

first:要擦除范围的开始。

last:要擦除范围的末尾。

通过迭代器擦除一个元素:

set<int> myset;
set<int>::iterator it;
myset = {
     10,20,30};
it=myset.find(10);
myset.erase (*it);
// erasing by iterator
cout<<"\n删除元素后: \n";
for (it=myset.begin(); it!=myset.end(); ++it)
    cout << *it << '\n';
//输出:20 30

用给定的键值删除集合中的元素:

set<int> myset;
set<int>::iterator it;
myset = {
     10, 20, 30, 40}; 
myset.erase (30);//删除指定值
cout<<"\n删除元素之后: \n";
for (it=myset.begin(); it!=myset.end(); ++it)
   cout << *it<< '\n';
//输出:10 20 40

以给定范围擦除元素:

set<int> myset;
set<int>::iterator it;
myset = {
     10, 20, 30};
cout<<"删除元素之前: \n";
cout<<"Size is: "<<myset.size()<<'\n';
      
myset.erase ( myset.begin () ,  myset.end () );
// 擦除指定范围
cout<<"\n删除元素之后: \n";
cout<<"Size is: "<<myset.size();
//输出:
//删除元素之前: Size is: 3
//删除元素之后: Size is: 0
  • clear()函数用于删除set容器的所有元素。清除集合并将其大小转换为0。
void clear();     
void clear() noexcept; 
set<int> myset = {
     10,20,30,40}; 
cout << "在清除操作前set集合初始大小 = " << myset.size() << endl;

myset.clear();
cout << "在清除操作后set集合大小 = " << myset.size() << endl;
//输出:在清除操作前set集合初始大小 = 4
//     在清除操作后set集合大小 = 0
  • swap()函数用于交换(或替换)两个集合的内容,但是两个集合的类型必须相同,尽管大小可能有所不同。
void swap (set& x);

参数
x:设置与之交换内容的容器。

set<int> m1 = {
     1,2,3,4,5};

set<int> m2;
m2.swap(m1);
cout << "集合包含以下元素" << endl;
for (auto it = m2.begin(); it != m2.end(); ++it)
    cout << *it<< endl;
//输出:集合包含以下元素:1 2 3 4 5
  • emplace()函数用于通过将新元素插入容器来扩展set容器。元素是直接构建的(既不复制也不移动)。
    通过给传递给该函数的参数args调用元素的构造函数。
    仅当键不存在时才进行插入。
template <class.... Args>
    pair<iterator, bool> emplace (Args&&... args);

参数
args:传递来构造要插入到集合中的元素的参数。

set<string> s1;  
auto ret = s1.emplace("ten");  
if (!ret.second)
    cout << "Emplace失败,值为“ten”的元素已经存在。";
else
	cout << "Emplace成功";
//输出:"Emplace成功"
  • emplace_hint()函数用于通过使用提示作为元素位置将新元素插入容器来扩展set容器。元素是直接构建的(既不复制也不移动)。
    通过给传递给该函数的参数args调用元素的构造函数。
    仅当密钥不存在时才进行插入。
template <class.... Args>
    iterator emplace_hint (const_iterator position, Args&&... args);

参数
args:传递来构造要插入到集合中的元素的参数。
position:提示插入新元素的位置。

set<int> m = {
     60, 20, 30, 40};           
m.emplace_hint(m.end(), 50);
m.emplace_hint(m.begin(), 10);
cout << "集包含以下元素" << endl;
for (auto it = m.begin(); it != m.end(); ++it)
    cout << *it<< endl;  
//输出:集包含以下元素 10 20 30 40 50 60

2.5、元素查找、操作

  • find()函数用于查找具有给定值 val 的元素。如果找到元素,则返回指向该元素的迭代器,否则返回指向集合末尾的迭代器,即set :: end()。
const_iterator find (const value_type& val) const;   
iterator       find (const value_type& val);             

参数
val:指定要在集合容器中搜索的值。

set<int> m = {
     100,200,300,400};
auto it = m.find(300);
cout << "迭代器指向 " << *it << endl;
//输出:迭代器指向 300
  • count()函数用于返回在容器中找到的元素数。由于set容器不包含任何重复元素,因此如果set容器中存在val值的元素,则此函数实际上返回1,否则返回0。
size_type count (const value_type& val) const;

参数
val:要在集合容器中搜索的值。

//初始化容器
set<int> mp;
 
// 按随机顺序插入元素
mp.insert(30);
mp.insert( 40 );
 
// 检查键30是否存在
if (mp.count(30))
    cout << "键30存在\n";
else
    cout << "键30不存在\n";
// 检查键100是否存在
if (mp.count(100))
    cout << "键100存在\n";
else
    cout << "键100不存在\n";
//输出:键30存在
//     键100不存在
  • lower_bound()函数用于返回一个迭代器,该迭代器指向set容器中的键,该键等效于参数中传递的val。
    如果在集合容器中没有val,它将返回一个迭代器,该迭代器指向比val大的下一个元素。
iterator lower_bound (const value_type& val);                
const_iterator lower_bound (const value_type& val) const; 

参数
val:要在集合容器中搜索的值。

set<char> m = {
     'a','c','e'};         
auto it = m.lower_bound('c');
cout << "下限(=) " << *it;
auto it = m.lower_bound('d');
cout << "下限(=) " << *it;
//输出:下限(=) c
//     下限(=) e
  • upper_bound()函数用于返回一个迭代器,该迭代器指向set容器中的值,该值大于参数中传递的val。
iterator upper_bound (const value_type& val);                 
const_iterator upper_bound (const value_type& val) const;     

参数
val:要在集合容器中搜索的值。

set<char> m = {
     'a','c','e'};         
auto it = m.upper_bound('a');
cout << "上限(=) " << *it;
auto it = m.upper_bound('c');
cout << "上限(=) " << *it;
//输出:上限(=) c
//     上限(=) e
  • equal_range()函数用于返回包含容器中等于val的所有元素的范围的边界。由于set容器中没有重复的值,因此此范围最多包含一个元素。
    如果val不匹配容器中的任何值,返回值范围将为0,两个迭代器都将指向最近的大于val的值,否则,如果val大于容器中的所有元素,它将指向end。
pair<const_iterator,const_iterator> equal_range (const value_type& val) const;
pair<iterator,iterator> equal_range (const value_type& val);

该范围由两个迭代器定义,一个指向不小于val的第一个元素,另一个指向大于val的第一个元素。
参数
val:要在集合容器中搜索的值。

set<char> m = {
     'a','b','c','d'};
auto ret = m.equal_range('b');
cout << "b的下限是: " << *ret.first<< endl;
cout << "b的上限是: " << *ret.second<< endl;
//输出:b的下限是: b
//     b的上限是: c

你可能感兴趣的:(C++,c++)