C++ STL multimap使用

C++ multimap使用

概述

  • 定义于头文件<map>
  • std::multimap 是有序键值对容器,它的元素的键是唯一的。用比较函数 Compare 排序键。搜索、移除和插入操作拥有对数复杂度。 multimap 通常实现为红黑树。

类模板:

template<
    class Key,
    class Compare = std::less<Key>,
    class Allocator = std::allocator<Key>
> class multimap;

创建multimap

构造函数

定义:

// 1、默认构造函数
multimap();	

// 2、范围构造函数。构造拥有范围 [first, last) 内容的容器。若范围中的多个元素拥有比较等价的关键,则插入哪个元素是未指定的								
template< class InputIt >
multimap( InputIt first, InputIt last,
     const Compare& comp = Compare(),
     const Allocator& alloc = Allocator() );

// 3、复制构造函数
multimap( const multimap& other );				

// 4、移动构造函数
multimap( multimap&& other );				 		

// 5、initializer_multimap init 构造函数
multimap( std::initializer_list<value_type> init,
     const Compare& comp = Compare(),
     const Allocator& alloc = Allocator() );

用法:

#include <iostream>
#include <string>
#include <iomanip>
#include <multimap>
 
template<typename Multimap>
void print_multimap(Multimap& m)
{
   std::cout << '{';
   for(auto& p: m)
        std::cout << p.first << ':' << p.second << ' ';
   std::cout << "}\n";
}
 
struct Point { double x, y; };
struct PointCmp {
    bool operator()(const Point& lhs, const Point& rhs) const { 
        return lhs.x < rhs.x; // NB 。有意忽略 y
    }
};
 
int main()
{
  // (1) 默认构造函数
  std::multimap<std::string, int> multimap1;
  multimap1["something"] = 69;
  multimap1["anything"] = 199;
  multimap1["that thing"] = 50;
  std::cout << "multimap1 = "; print_multimap(multimap1);
 
  // (2) 范围构造函数
  std::multimap<std::string, int> iter(multimap1.find("anything"), multimap1.end());
  std::cout << "\niter = "; print_multimap(iter);
  std::cout << "multimap1 = "; print_multimap(multimap1);
 
  // (3) 复制构造函数
  std::multimap<std::string, int> copied(multimap1);
  std::cout << "\ncopied = "; print_multimap(copied);
  std::cout << "multimap1 = "; print_multimap(multimap1);
 
  // (4) 移动构造函数
  std::multimap<std::string, int> moved(std::move(multimap1));
  std::cout << "\nmoved = "; print_multimap(moved);
  std::cout << "multimap1 = "; print_multimap(multimap1);
 
  // (5) initializer_list 构造函数
  const std::multimap<std::string, int> init {
    {"this", 100},
    {"can", 100},
    {"be", 100},
    {"const", 100},
  };
  std::cout << "\ninit = "; print_multimap(init);
 
 
  // 定制关键类选项 1 :
  // 使用比较 struct
  std::multimap<Point, double, PointCmp> mag = {
      { {5, -12}, 13 },
      { {3, 4},   5 },
      { {-8, -15}, 17 }
  };
 
  for(auto p : mag)
      std::cout << "The magnitude of (" << p.first.x
                << ", " << p.first.y << ") is "
                << p.second << '\n';
 
  // 定制关键类选项 2 :
  // 使用比较 lambda
  // 此 lambda 按照其模比较点,注意其中模取自局部变量 mag
  auto cmpLambda = [&mag](const Point &lhs, const Point &rhs) { return mag[lhs] < mag[rhs]; };
  // 你亦可使用不依赖局部变量的 lambda ,像这样:
  // auto cmpLambda = [](const Point &lhs, const Point &rhs) { return lhs.y < rhs.y; };
  std::multimap<Point, double, decltype(cmpLambda)> magy(cmpLambda);
 
  // 各种插入元素的方式:
  magy.insert(std::pair<Point, double>({5, -12}, 13));
  magy.insert({ {3, 4}, 5});
  magy.insert({Point{-8.0, -15.0}, 17});
 
  std::cout << '\n';
  for(auto p : magy)
      std::cout << "The magnitude of (" << p.first.x
                << ", " << p.first.y << ") is "
                << p.second << '\n';
}

// 输出
// multimap1 = {anything:199 something:69 that thing:50 }
 
// iter = {anything:199 something:69 that thing:50 }
// multimap1 = {anything:199 something:69 that thing:50 }
 
// copied = {anything:199 something:69 that thing:50 }
// multimap1 = {anything:199 something:69 that thing:50 }
 
// moved = {anything:199 something:69 that thing:50 }
// multimap1 = {}
 
// init = {be:100 can:100 const:100 this:100 }
// The magnitude of (-8, -15) is 17
// The magnitude of (3, 4) is 5
// The magnitude of (5, -12) is 13
 
// The magnitude of (3, 4) is 5
// The magnitude of (5, -12) is 13
// The magnitude of (-8, -15) is 17

opertor=

  • 赋值给容器
    定义:
multimap& operator=( const multimap& other );	// 复制赋值运算符。
multimap& operator=( multimap&& other );	// 移动赋值运算符。
multimap& operator=( std::initializer_multimap<T> imultimap ); // 以 initializer_multimap imultimap 所标识者替换内容。

用法:

    std::multimap<int, int> nums1 {{3, 1}, {4, 1}, {5, 9}, 
                              {6, 1}, {7, 1}, {8, 9}};
    std::multimap<int, int> nums2; 
    std::multimap<int, int> nums3;

    // 从 nums1 复制赋值数据到 nums2
    nums2 = nums1;
    // 从 nums1 移动赋值数据到 nums3,
    nums3 = std::move(nums1);
    // initializer_multimap 的复制赋值复制数据给 nums1
    nums1 = {{3, 1}, {4, 1}, {5, 9}};

元素访问

at

  • 访问指定的元素,同时进行越界检查
T& at( const Key& key );

const T& at( const Key& key ) const;
  • 参数:key - 要找到的元素的键
  • 返回值:value,键对应的值

operator[ ]

  • 访问插入指定的元素

定义:

T& operator[]( const Key& key );

T& operator[]( Key&& key );

用法:

#include <iostream>
#include <string>
#include <vector>
#include <multimap>
 
int main()
{
    std::multimap<char, int> letter_counts {{'a', 27}, {'b', 3}, {'c', 1}};
 
    std::cout << "initially:\n";
    for (const auto &pair : letter_counts) {
        std::cout << pair.first << ": " << pair.second << '\n';
    }
 
    letter_counts['b'] = 42;  // 更新既存值
    letter_counts['x'] = 9;  // 插入新值
 
    std::cout << "after modifications:\n";
    for (const auto &pair : letter_counts) {
        std::cout << pair.first << ": " << pair.second << '\n';
    }
 
    // 统计每个词的出现数
    // (首次调用 operator[] 以零初始化计数器)
    std::multimap<std::string, size_t>  word_multimap;
    for (const auto &w : { "this", "sentence", "is", "not", "a", "sentence",
                           "this", "sentence", "is", "a", "hoax"}) {
        ++word_multimap[w];
    }
 
    for (const auto &pair : word_multimap) {
        std::cout << pair.second << " occurrences of word '" << pair.first << "'\n";
    }
}

// 输出
initially:
a: 27
b: 3
c: 1
after modifications:
a: 27
b: 42
c: 1
x: 9
2 occurrences of word 'a'
1 occurrences of word 'hoax'
2 occurrences of word 'is'
1 occurrences of word 'not'
3 occurrences of word 'sentence'
2 occurrences of word 'this'

迭代器

begin\cbegin

在这里插入图片描述

  • 返回指向 multimap 首元素的迭代器。
  • cbegin中的c表示const,即返回const_iterator,不允许通过迭代器修改元素。
  • 若 multimap 为空,则返回的迭代器将等于 end() 。

定义:

iterator begin();
const_iterator cbegin() const noexcept;

用法:

#include <iostream>
#include <multimap>
 
int main() {
  std::multimap<int, float> num_multimap;
  num_multimap[4] = 4.13;
  num_multimap[9] = 9.24;
  num_multimap[1] = 1.09;
  // 调用 a_multimap.begin() 与 a_multimap.end()
  for (auto it = num_multimap.begin(); it != num_multimap.end(); ++it) {
    std::cout << it->first << ", " << it->second << '\n';
  }
}

// 输出
// 1, 1.09
// 4, 4.13
// 9, 9.24

end\cend

  • 返回指向 multimap 末元素后一元素的迭代器。

定义:

iterator end();
const_iterator cend() const noexcept;

rbegin\crbegin

在这里插入图片描述

  • 返回指向逆向 multimap 首元素的逆向迭代器。
  • 它对应非逆向 multimap 的末元素。若 multimap 为空,则返回的迭代器等于 rend() 。

定义:

reverse_iterator rbegin();
const_reverse_iterator crbegin() const noexcept;

rend\crend

  • 返回指向逆向 multimap 末元素后一元素的逆向迭代器。
  • 它对应非逆向 multimap 首元素的前一元素。此元素表现为占位符,试图访问它导致未定义行为。

定义:

reverse_iterator rend();
const_reverse_iterator crend() const noexcept;

容量

empty

  • 检查容器是否无元素,即是否 begin() == end() 。

定义:

bool empty() const;

用法:

	multimap<int, int> v;
	bool flag = v.empty();	// 输出 true

size

  • 返回容纳的元素数。 即 std::distance(begin(), end()) 。

定义:

size_type size() const;

用法:

    std::multimap<int,char> nums {{1, 'a'}, {3, 'b'}, {5, 'c'}, {7, 'd'}};
    std::cout << nums.size() << std::endl;	// 输出 4

max_size

  • 返回根据系统或库实现限制的容器可保有的元素最大数量,即对于最大容器的 std::distance(begin(), end()) 。

定义:

size_type max_size() const;

用法:

	std::multimap<int, int> vi;
	std::cout << vi.max_size() << std::endl;	// 可能输出 4611686018427387903
	std::multimap<char, cahr> vc;
	std::cout << vc.max_size() << std::endl;	// 可能输出 18446744073709551615

修改器

clear

  • 从容器擦除所有元素。此调用后 size() 返回零。
  • 非法化任何指代所含元素的引用、指针或迭代器。任何尾后迭代器亦被非法化。

定义:

void clear();

用法:

	std::multimap<int, char> container{{1, 'a'}, {3, 'b'}, {5, 'c'}};
	container.clear();
	std::cout << container.size() << std::endl;		// 输出 0

insert

  • 插入元素或结点

定义:

std::pair<iterator,bool> insert( const value_type& value );

std::pair<iterator,bool> insert( value_type&& value );

template< class InputIt >
void insert( InputIt first, InputIt last );

void insert( std::initializer_list<value_type> ilist );

用法:

    std::multimap<int, char> a;
 	
 	a.insert({1, 'a'});

	std::multimap<int, char> b { {3, 'b'}, {5, 'c'}};
	a.insert(b.begin(), b.end());
	
 	a.insert({7, 'd'}, {9, 'e'});

emplace

  原位构造元素
定义:

template< class... Args >
std::pair<iterator,bool> emplace( Args&&... args );;

emplace_hint

  • 使用提示原位构造元素
  • 返回值
      返回指向新插入元素的迭代器。
      若因元素已存在而插入失败,则返回指向拥有等价关键的既存元素的迭代器。

定义:

template <class... Args>
iterator emplace_hint( const_iterator hint, Args&&... args );

erase

  • 从容器擦除指定的元素。

定义:

// 1、移除位于 pos 的元素。
iterator erase( iterator pos );

// 2、移除范围 [first; last) 中的元素。
iterator erase( iterator first, iterator last );

// 3、移除关键等于 key 的元素(若存在一个)。
size_type erase( const key_type& key )

用法:

    std::multimap<int, char> c = {{3, 'b'}, {4, 'c'}, {2, 'b'}, {5, 'c'}};
    // 从 c 擦除所有奇数
    for(auto it = c.begin(); it != c.end(); )
        if(it->first % 2 == 1)
            it = c.erase(it);
        else
            ++it;
     // c : 2 4 6 8

swap

  • 交换内容

定义:

void swap( multimap& other );

用法:

	std::multimap<int, char> a1{{3, 'b'}}, a2{{4, 'c'}, {2, 'b'}};
	a1.swap(a2);

extract

  • 从另一容器释出结点 C++17

定义:

// 解链含 position 所指向元素的结点并返回占有它的结点柄。
node_type extract( const_iterator position );

// 若容器拥有元素而其关键等于 x ,则从容器解链该元素并返回占有它的结点柄。否则,返回空结点柄。
node_type extract( const key_type& x );

merge

  • 从另一容器接合结点 C++17

定义:

template<class C2>
void merge( std::multimap<Key, C2, Allocator>& source );

template<class C2>
void merge( std::multimap<Key, C2, Allocator>&& source );

用法:

  	std::multimap<int, std::string> ma {{1, "apple"}, {5, "pear"}, {10, "banana"}};
  	std::multimap<int, std::string> mb {{2, "zorro"}, {4, "batman"}, {5, "X"}, {8, "alpaca"}};
  	std::multimap<int, std::string> u;
 	 u.merge(ma);
  	std::cout << "ma.size(): " << ma.size() << '\n';
  	u.merge(mb);
  	std::cout << "mb.size(): " << mb.size() << '\n';
  	std::cout << "mb.at(5): " << mb.at(5) << '\n';
  	for(auto const &kv: u)
    	std::cout << kv.first << ", " << kv.second << '\n';

// 输出
ma.size(): 0
mb.size(): 1
mb.at(5): X
1, apple
2, zorro
4, batman
5, pear
8, alpaca
10, banana

查找

count

  • 返回匹配特定键的元素数量
  • 返回拥有关键比较等价于指定参数的元素数,因为此容器不允许重复故为 1 或 0。

定义:

size_type count( const Key& key ) const;

find

  • 寻找带有特定键的元素
  • 返回值
      指向键等于 key 的元素的迭代器。若找不到这种元素,则返回尾后(见 end() )迭代器。

定义:

iterator find( const Key& key );
const_iterator find( const Key& key ) const;

用法:

	std::multimap<int,char> example = {{1,'a'},{2,'b'}};
 
    auto search = example.find(2);
    if (search != example.end()) {
        std::cout << "Found " << (*search) << '\n';
    } else {
        std::cout << "Not found\n";
    }

contains

  • 检查容器中是否有键等价于 key 的元素
  • 若有这种元素则返回 true ,否则返回 false

定义:

bool contains( const Key& key ) const;

template< class K > bool contains( const K& x ) const;

用法:

	std::multimap<int,char> example = {{1,'a'},{2,'b'}};
 
    for(int x: {2, 5}) {
        if(example.contains(x)) {
            std::cout << x << ": Found\n";
        } else {
            std::cout << x << ": Not found\n";
        }
    }

equal_range

  • 返回匹配特定键的元素范围
  • 范围以二个迭代器定义,一个指向首个不小于 key 的元素,另一个指向首个大于 key 的元素。首个迭代器可以换用 lower_bound() 获得,而第二迭代器可换用 upper_bound() 获得。
  • 返回值: 含一对定义所需范围的迭代器的 std::pair :第一个指向首个不小于 key 的元素,第二个指向首个大于 key 的元素。

若无元素不小于 key ,则将尾后(见 end() )迭代器作为第一元素返回。类似地,若无元素大于 key ,则将尾后迭代器作为第二元素返回。

定义:

std::pair<iterator,iterator> equal_range( const Key& key );

lower_bound

  • 返回指向首个不小于给定键的元素的迭代器
  • 指向首个不小于 key 的元素的迭代器。若找不到这种元素,则返回尾后迭代器。

定义:

iterator lower_bound( const Key& key );

用法见upper_bound。

upper_bound

  • 返回指向首个大于给定键的元素的迭代器
  • 指向首个大于 key 的元素的迭代器。若找不到这种元素,则返回尾后(见 end() )迭代器。

定义:

iterator upper_bound( const Key& key );

用法:

	std::multimap<int, char> a {{1,'a'},{2,'b'}, {3,'c'}, {4,'d'}};
	std::cout << a.lower_bound(3)->second << std::endl;	// 3
	std::cout << a.upper_bound(3) << std::endl;	// 4

观察器

key_comp

  • 返回用于比较键的函数
  • 它是此容器构造函数参数 comp 的副本,它与 value_comp 相同。
key_compare key_comp() const;

value_comp

  • 返回比较 std::multimap::value_type (关键-值 pair )对象的函数对象,它用 key_comp 比较 pair 的第一组分。
  • 返回值
      比较值的函数对象。
std::multimap::value_compare value_comp() const;

非成员函数

operator==

  • 按照字典顺序比较 multimap 中的值

定义:

template< class Key, class Compare, class Alloc >
bool operator==( const std::multimap<Key,Compare,Alloc>& lhs,
                 const std::multimap<Key,Compare,Alloc>& rhs );

用法:

    std::multimap<int, char> alice{{1, 'a'}, {2, 'b'}, {3, 'c'}};
    std::multimap<int, char> bob{{7, 'Z'}, {8, 'Y'}, {9, 'X'}, {10, 'W'}};
    std::multimap<int, char> eve{{1, 'a'}, {2, 'b'}, {3, 'c'}};
 
	// 比较不相等的容器
	std::cout << "alice == bob returns " << (alice == bob) << std::endl;	//输出 false
	// 比较相等的容器
	std::cout << "alice == eve returns " << (alice == eve) << std::endl;	//输出 true

std::swap(std::multimap)

  • 为 std::multimap 特化 std::swap 算法。交换 lhs 与 rhs 的内容。调用 lhs.swap(rhs) 。

定义:

template< class Key, class Compare, class Alloc >
void swap( std::multimap<Key,Compare,Alloc>& lhs,
           std::multimap<Key,Compare,Alloc>& rhs );

用法:

    std::multimap<int, char> alice{{1, 'a'}, {2, 'b'}, {3, 'c'}};
    std::multimap<int, char> bob{{7, 'Z'}, {8, 'Y'}, {9, 'X'}, {10, 'W'}};
	//交换容器
	std::swap(alice,bob);

erase_if(std::multimap)

  • 擦除所有满足特定判别标准的元素(C++ 20)

定义:

template< class Key, class Compare, class Alloc, class Pred >
typename std::multimap<Key,Compare,Alloc>::size_type
    erase_if(std::multimap<Key,Compare,Alloc>& c, Pred pred);

用法:

    std::multimap<int, char> data {{1, 'a'},{2, 'b'},{3, 'c'},{4, 'd'},
                              {5, 'e'},{4, 'f'},{5, 'g'},{5, 'g'}};
    std::cout << "Original:\n" << data << '\n';
 
    const auto count = std::erase_if(data, [](const auto& item) {
        auto const& [key, value] = item;
        return (key & 1) == 1;
    });
    // {{2, b}{4, d}}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值