【C++】set map 使用

目录

[1. set 和 map 的与其他类型的介绍对比](#1. set 和 map 的与其他类型的介绍对比)

[2. set 的系列介绍](#2. set 的系列介绍)

[2.1 set 和 multiset 的相关文献](#2.1 set 和 multiset 的相关文献)

[2.2 set 的初始化函数](#2.2 set 的初始化函数)

[2.3 set 的增删改函数](#2.3 set 的增删改函数)

[2.4 set 的其他函数](#2.4 set 的其他函数)

[2.5 set 和 multiset 的对比](#2.5 set 和 multiset 的对比)

[3. map 的系列介绍](#3. map 的系列介绍)

[3.1 map 和 multimap 的相关文献](#3.1 map 和 multimap 的相关文献)

[3.2 map 的初始化函数](#3.2 map 的初始化函数)

[3.3 map 的增删改函数](#3.3 map 的增删改函数)

[3.4 map 的其他函数](#3.4 map 的其他函数)

[3.5 map 的 operator\[\] 运算符重载](#3.5 map 的 operator[] 运算符重载)

[3.6 pair 类的介绍](#3.6 pair 类的介绍)

[3.7 map 和 multimap 的对比](#3.7 map 和 multimap 的对比)


1. set 和 map 的与其他类型的介绍对比

与之前的类型的对比 string vector list stack queue deque priority_queue 等的类型的,set 和 map 的类型与二叉搜索树关系更加相似,但他们的底层是以红黑树构成的,如果你现在还没有了解红黑树的话,那就先以比二叉搜索树更加牛逼的理解就可以。

在二叉搜索树章节中我们有稍微熟悉了二叉搜索树的底层,其中二叉搜索树中的结构有两个类型有关是 class K 和 class V , K 对应的是 _key 全部二叉搜索树的比较基准都是以 _key 为标准,V对应的是 _value 是附加的类型,set 就是两类型中有 _key 一个,map 就是有两个。


2. set 的系列介绍

2.1 set 和 multiset 的相关文献

set - C++ Reference multiset - C++ Reference

2.2 set 的初始化函数

cpp 复制代码
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;
// 默认 set 左子树小 右子树大
cpp 复制代码
empty (1) // 默认构造	
explicit set (const key_compare& comp = key_compare(),
              const allocator_type& alloc = allocator_type());
range (2) // 一段区间构造	
template <class InputIterator>
  set (InputIterator first, InputIterator last,
       const key_compare& comp = key_compare(),
       const allocator_type& alloc = allocator_type());
copy (3) // 拷贝构造	
set (const set& x);

copy (1) // 等号运算算符重载	
 set& operator= (const set& x);

2.3 set 的增删改函数

cpp 复制代码
// insert
single element (1)	// 单个插入
pair<iterator,bool> insert (const value_type& val);
with hint (2)	// 
iterator insert (iterator position, const value_type& val);
range (3)	// 区间插入
template <class InputIterator>
  void insert (InputIterator first, InputIterator last);

// erase 
(1)	// 指定区间删除
     void erase (iterator position);
(2)	// 指定内容删除 // 看完 multiset 的话: 指定内容删除并且返回(size_t)n
size_type erase (const value_type& val);
(3)	// 指定区间删除(要配合迭代器使用)
     void erase (iterator first, iterator last);

// swap 交换
void swap (set& x);
// 清空
void clear();

2.4 set 的其他函数

cpp 复制代码
// begin end rbegin rend
// begin 返回最小值的迭代器
      iterator begin();
const_iterator begin() const;
// end   返回最大值的迭代器
      iterator end();
const_iterator end() const;
// rbegin 返回最大值的迭代器
      iterator rbegin();
const_iterator rbegin() const;
// rend   返回最小值的迭代器
      iterator rend();
const_iterator rend() const;

// empty 判断是否为空
bool empty() const;

// size 返回已经节点有多少个 
size_type size() const;

// count 检查是否有这个数,有就返回1,没有返回0
size_type count (const value_type& val) const;

// find 查找 给 val 返回地址
iterator find (const value_type& val) const;

// lower_bound 输入的数值返回地址,如果数值没有,查找比这个大的数值
iterator lower_bound (const value_type& val) const;
// upper_bound 输入的数值返回地址,如果数值没有,查找比这个小的数值
iterator upper_bound (const value_type& val) const;
// 两个对比 lower_bound 查找最大下限  upper_bound 查找最小上限
// equal_range 返回最大下限和最小上限 两个的结合
pair<iterator,iterator> equal_range (const value_type& val) const;

lower_bound 和 upper_bound 针对的是不同_ket 之间查找有效区间的;

equal_range 针对的是相同_ket 的有效区间 例如:1,2,2,2,3 就会把以一个2和最后一个3,有效区间 [2,3) 一起打包到pair<iterator,iterator>这个类中

cpp 复制代码
void test_set1()
{
	int arr[] = { 9,3,7,4,2,85,42,13,34 };
	set<int> s(arr, arr + 9);
	s.insert(10);
	for (auto ch : s)
	{
		cout << ch << " ";
	}
	cout << endl;

	s.erase(10);
	for (auto ch : s)
	{
		cout << ch << " ";
	}
	cout << endl;
	s.erase(s.begin());
	for (auto ch : s)
	{
		cout << ch << " ";
	}
	cout << endl;

	s.erase(s.begin(),s.end());
	s.insert(10);
	for (auto ch : s)
	{
		cout << ch << " ";
	}
	cout << endl;
	return;
}

2.5 set 和 multiset 的对比

  1. 元素是否允许重复
  • set:不允许重复键值,容器内元素唯一;插入重复值会直接失败,不会新增元素。
  • multiset:允许重复元素,可以存放多个相同的值,插入重复值成功。
cpp 复制代码
set<int> s;
s.insert(1);
s.insert(1); // 无效,s 里只有一个1

multiset<int> ms;
ms.insert(1);
ms.insert(1); // 有效,ms 里有两个1
  1. 查找删除接口行为差异(高频考点)
  • find(val):返回第一个等于 val 的元素迭代器,两者行为一致。
  • count(val)
    • set:返回只能是 0 或 1
    • multiset:返回有多少个等于 val 的元素
  • erase(val)(传值,不是迭代器!)
    • set.erase(val):删除值为 val 的那一个元素
    • multiset.erase(val):删除所有值等于 val 的元素
  • 如果只想删掉 multiset 里其中一个:
cpp 复制代码
auto it = ms.find(val);
if (it != ms.end()) ms.erase(it);

3. map 的系列介绍

3.1 map 和 multimap 的相关文献

map - C++ Reference multimap - C++ Reference

3.2 map 的初始化函数

cpp 复制代码
template < class Key,                                     // map::key_type
           class T,                                       // map::mapped_type
           class Compare = less<Key>,                     // map::key_compare
           class Alloc = allocator<pair<const Key,T> >    // map::allocator_type
           > class map;

	
typedef pair<const Key, T> value_type;
cpp 复制代码
// 构造函数
empty (1)	
explicit map (const key_compare& comp = key_compare(),
              const allocator_type& alloc = allocator_type());
range (2)	
template <class InputIterator>
  map (InputIterator first, InputIterator last,
       const key_compare& comp = key_compare(),
       const allocator_type& alloc = allocator_type());
copy (3)	
map (const map& x);
// 赋值运算符重载
copy (1)	
 map& operator= (const map& x);

3.3 map 的增删改函数

cpp 复制代码
// insert 插入
single element (1)	// 单个插入
pair<iterator,bool> insert (const value_type& val);
with hint (2)	//
iterator insert (iterator position, const value_type& val);
range (3)	// 指定区间插入
template <class InputIterator>
  void insert (InputIterator first, InputIterator last);
// erase 删除
(1)	// 指定地址删除
     void erase (iterator position);
(2)	// 指定内容删除
size_type erase (const key_type& k);
(3)	// 指定区间删除
     void erase (iterator first, iterator last);
// swap 交换
void swap (map& x);
// clear 清空
void clear();

3.4 map 的其他函数

cpp 复制代码
// begin end rbegin rend
// begin 返回最小值的迭代器
      iterator begin();
const_iterator begin() const;
// end   返回最大值的迭代器
      iterator end();
const_iterator end() const;
// rbegin 返回最大值的迭代器
      iterator rbegin();
const_iterator rbegin() const;
// rend   返回最小值的迭代器
      iterator rend();
const_iterator rend() const;

// empty 判断是否为空
bool empty() const;

// size 返回已经节点有多少个 
size_type size() const;

// count 检查是否有这个数,有就返回1,没有返回0
size_type count (const key_type& val) const;

// find 查找 给 val 返回地址
iterator find (const key_type& val) const;

// lower_bound 输入的数值返回地址,如果数值没有,查找比这个大的数值
iterator lower_bound (const key_type& val) const;
// upper_bound 输入的数值返回地址,如果数值没有,查找比这个小的数值
iterator upper_bound (const key_type& val) const;
// 两个对比 lower_bound 查找最大下限  upper_bound 查找最小上限
// equal_range 返回最大下限和最小上限 两个的结合
pair<iterator,iterator> equal_range (const key_type& val) const;

3.5 map 的 operator\[\] 运算符重载

cpp 复制代码
mapped_type& operator[] (const key_type& k);

map 的operator\[\] 运算符重相对于 vector 等的不一样(注意 multimap 没有这个运算符重载),相当于如果 k 在 map 中存在就返回对应地址,并且可以进行修改 map 中的 value 的(不是 ket),如果没有就会就会在这个区域进行插入新_key 空间,后面与前者的功能一致。

3.6 pair 类的介绍

pair - C++ Reference

cpp 复制代码
template<class T1, class T2>
struct pair
{
    T1 first;   // 第一个成员
    T2 second;  // 第二个成员
};

pair 是一个拥有两个自定义类型模板结构体,在 map 常被用来当做 typedef pair<const Key, T> value_type; 头文件:#include <utility>

pair 类型还有内置的运算符重载

优先比较 first ,其次比较 second

cpp 复制代码
template <class T1, class T2>
  bool operator== (const pair<T1,T2>& lhs, const pair<T1,T2>& rhs)
{ return lhs.first==rhs.first && lhs.second==rhs.second; }

template <class T1, class T2>
  bool operator!= (const pair<T1,T2>& lhs, const pair<T1,T2>& rhs)
{ return !(lhs==rhs); }

template <class T1, class T2>
  bool operator<  (const pair<T1,T2>& lhs, const pair<T1,T2>& rhs)
{ return lhs.first<rhs.first || (!(rhs.first<lhs.first) && lhs.second<rhs.second); }

template <class T1, class T2>
  bool operator<= (const pair<T1,T2>& lhs, const pair<T1,T2>& rhs)
{ return !(rhs<lhs); }

template <class T1, class T2>
  bool operator>  (const pair<T1,T2>& lhs, const pair<T1,T2>& rhs)
{ return rhs<lhs; }

template <class T1, class T2>
  bool operator>= (const pair<T1,T2>& lhs, const pair<T1,T2>& rhs)
{ return !(lhs<rhs); }

pair 的使用

cpp 复制代码
#include <iostream>
#include <map>
#include <utility>
#include <string>
using namespace std;

int main()
{
    map<int, string> mp;

    mp.insert(make_pair(1, "C++"));
    mp.insert({2, "Java"});
    mp[3] = "Python";

    for(auto &p : mp)
    {
        cout << p.first << " : " << p.second << endl;
    }

    auto it = mp.find(2);
    if(it != mp.end())
    {
        it->second = "GO";
    }

    return 0;
}

3.7 map 和 multimap 的对比

同理 map 和 multimap 都属于关联容器 ,底层都是红黑树(平衡二叉搜索树) ,元素按键key有序排列,迭代器遍历是升序;核心差别:map 键不允许重复,multimap 允许 key 重复。

相关推荐
用户093671755411 小时前
用 4500 行 TypeScript 复刻了童年方格纸上的海战棋
前端·vue.js
CCIE-Yasuo1 小时前
网络安全-学习web开发-基础概念、常用标签
前端·学习
艾莉丝努力练剑1 小时前
【AI大模型接入SDK】ChatServer问题修复
c++·学习·ai·大模型·sdk
凉介川1 小时前
给 DeepSeek Harness 写插件:按扩展名接管 Windows 右键打开
前端
涛涛ing1 小时前
Pretext之后,2026年的前端正在被“平台”和“AI”同时重写
前端
yuniko-n1 小时前
【JUC】Thread 内存泄露
java
freejackman1 小时前
【架构篇】双遍历 + 多栈协同:手撸 SQL 血缘引擎的架构思考
java·大数据·数据库·hive·sql·架构·spark
企业数字化笔记2 小时前
业务单据怎样接入流程中心?启动条件、实例关联与失败回退
java·spring boot·mysql
挖掘狂人2 小时前
同一个端口能不能被两个程序同时监听?
java·后端·程序员