容器库(8)-std::multiset

std::multiset是以key为元素的有序关联容器,和std::set不同的是,std::multiset中的key可以重复。搜索、移除和插入的时间复杂度是对数复杂度。

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

本文章的代码库:

https://gitee.com/gamestorm577/CppStd

成员函数

构造、析构和赋值

构造函数

可以用迭代器、另一个multiset或者元素列表来构造一个multiset。代码示例:

std::vector vec{1, 1, 2, 2, 3};

std::multiset m1(vec.begin(), vec.end());
std::multiset m2(m1);
std::multiset m3{1, 2, 2, 2, 2, 3, 3, 4};

std::cout << "m1 size = " << m1.size() << std::endl;
std::cout << "m2 size = " << m2.size() << std::endl;
std::cout << "m3 size = " << m3.size() << std::endl;

输出结果:

m1 size = 5
m2 size = 5
m3 size = 8

析构函数

删除multiset时,会调用各元素的析构函数。代码示例:

struct MyStruct
{
    MyStruct(int i)
        : Index(i)
    {
    }

    ~MyStruct()
    {
        std::cout << "destruct, Index = " << Index << std::endl;
    }

    int Index = 0;
};

struct MyStructCmp
{
    bool operator()(const MyStruct& lhs, const MyStruct& rhs) const
    {
        return lhs.Index < rhs.Index;
    }
};

std::multiset s{1, 2, 2, 3};
std::cout << "end" << std::endl;

输出结果:

destruct, Index = 3
destruct, Index = 2
destruct, Index = 2
destruct, Index = 1
end
destruct, Index = 1
destruct, Index = 3
destruct, Index = 2
destruct, Index = 2

赋值函数

可以用另一个set或者元素列表给set赋值。代码示例:

std::multiset tmp{1, 1, 2, 2};
std::multiset m1;
std::multiset m2;

m1 = tmp;
m2 = {1, 1, 2, 2, 3};
std::cout << "m1 size = " << m1.size() << std::endl;
std::cout << "m2 size = " << m2.size() << std::endl;

输出结果:

m1 size = 4
m2 size = 5

迭代器

接口begin、cbegin指向multiset起始的迭代器,end、cend指向末尾的迭代器。rbegin、crbegin指向起始的逆向迭代器,rend、crend指向末尾的逆向迭代器。无论什么迭代器都不能修改元素的值。代码示例:

std::multiset m{1, 2, 2, 3};
for (auto iter = m.begin(); iter != m.end(); ++iter)
{
    std::cout << "num is: " << *iter << std::endl;
}

输出结果:

num is: 1
num is: 2
num is: 2
num is: 3

容量

empty

检查multiset是否为空。代码示例:

std::multiset m1{1, 2, 2, 3};
std::multiset m2;
std::cout << std::boolalpha;
std::cout << "m1 empty: " << m1.empty() << std::endl;
std::cout << "m2 empty: " << m2.empty() << std::endl;

输出结果:

m1 empty: false
m2 empty: true

size

获取multiset中元素的个数。代码示例:

std::set m1{1, 2, 2, 3};
std::set m2;
std::cout << "m1 size = " << m1.size() << std::endl;
std::cout << "m2 size = " << m2.size() << std::endl;

输出结果:

m1 size = 3
m2 size = 0

max_size

返回可以容纳的最大元素个数。代码示例:

std::set m1;
std::set m2;
std::cout << "m1 max size = " << m1.max_size() << std::endl;
std::cout << "m2 max size = " << m2.max_size() << std::endl;

输出结果:

m1 max size = 576460752303423487
m2 max size = 461168601842738790

修改器

clear

清除所有的元素。代码示例:

std::set m{1, 2, 2, 3};
std::cout << "m size = " << m.size() << std::endl;
m.clear();
std::cout << "m size = " << m.size() << std::endl;

输出结果:

m size = 3
m size = 0

insert

插入元素,参数可以是元素、迭代器或者元素节点。代码示例:

std::multiset m{1, 2, 2};
m.insert(2);
std::cout << "m size = " << m.size() << std::endl;

std::vector tmp{2, 2, 3, 3, 3};
m.insert(tmp.begin(), tmp.end());
std::cout << "m size = " << m.size() << std::endl;

输出结果:

m size = 4
m size = 9

emplace

构造一个元素到multiset中。代码示例:

struct MyStruct
{
    MyStruct(int num1, int num2)
        : Num1(num1)
        , Num2(num2)
    {
    }

    int Num1;
    int Num2;
};

struct MyStructCmp
{
    bool operator()(const MyStruct& lhs, const MyStruct& rhs) const
    {
        return lhs.Num1 < rhs.Num2;
    }
};

std::multiset m;
m.emplace(1, 10);
std::cout << "m size = " << m.size() << std::endl;
m.emplace(1, 10);
std::cout << "m size = " << m.size() << std::endl;

输出结果:

m size = 1
m size = 2

emplace_hint

向multiset中尽可能靠近hint之前的位置插入新元素:

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

不同的hint会导致插入元素的效率不同。代码示例:

auto timer = [](std::function func, std::string tag) -> void
{
    auto start = std::chrono::system_clock::now();
    std::size_t size = func();
    auto end = std::chrono::system_clock::now();
    std::chrono::duration time = end - start;
    std::cout << tag << ", size: " << size << ", use time: " << time.count()
              << std::endl;
};

const int count = 2000000;

auto multiset_emplace = [=]() -> std::size_t
{
    std::multiset m;
    for (int i = 0; i < count; ++i)
    {
        m.emplace(i);
    }
    return m.size();
};

auto multiset_emplace_hint1 = [=]() -> std::size_t
{
    std::multiset m;
    auto iter = m.begin();
    for (int i = 0; i < count; ++i)
    {
        m.emplace_hint(iter, i);
        iter = m.end();
    }
    return m.size();
};

auto multiset_emplace_hint2 = [=]() -> std::size_t
{
    std::multiset m;
    auto iter = m.begin();
    for (int i = 0; i < count; ++i)
    {
        m.emplace_hint(iter, i);
        iter = m.begin();
    }
    return m.size();
};

auto multiset_emplace_hint3 = [=]() -> std::size_t
{
    std::multiset m;
    auto iter = m.begin();
    for (int i = 0; i < count; ++i)
    {
        iter = m.emplace_hint(iter, i);
    }
    return m.size();
};

timer(multiset_emplace, "multiset_emplace");
timer(multiset_emplace_hint1, "multiset_emplace_hint1");
timer(multiset_emplace_hint2, "multiset_emplace_hint2");
timer(multiset_emplace_hint3, "multiset_emplace_hint3");

输出结果:

multiset_emplace, size: 2000000, use time: 779.65
multiset_emplace_hint1, size: 2000000, use time: 639.442
multiset_emplace_hint2, size: 2000000, use time: 750.817
multiset_emplace_hint3, size: 2000000, use time: 860.849

erase

移除指定位置或者指定值的元素。代码示例:

std::multiset m{1, 1, 1, 2, 2, 2, 3, 17, 17, 17};
std::cout << "m size = " << m.size() << std::endl;
m.erase(m.begin());
std::cout << "m size = " << m.size() << std::endl;
m.erase(m.begin(), std::next(m.begin(), 2));
std::cout << "m size = " << m.size() << std::endl;
m.erase(17);
std::cout << "m size = " << m.size() << std::endl;

输出结果:

m size = 10
m size = 9
m size = 7
m size = 4

swap

和另一个multiset交换元素内容。代码示例:

std::multiset m1{1, 1, 1, 2};
std::multiset m2{1, 2};
m1.swap(m2);
std::cout << "m1 size = " << m1.size() << std::endl;
std::cout << "m2 size = " << m2.size() << std::endl;

输出结果:

m1 size = 2
m2 size = 4

extract

提取map中的某个位置或首个等于某个值的元素节点,提取后multiset不再拥有该元素。代码示例:

std::multiset m{1, 1, 1, 2};
std::cout << "m size = " << m.size() << std::endl;
m.extract(1);
std::cout << "m size = " << m.size() << std::endl;
auto iter = m.extract(2);
std::cout << "m size = " << m.size() << std::endl;
m.insert(std::move(iter));
std::cout << "m size = " << m.size() << std::endl;

输出结果:

m size = 4
m size = 3
m size = 2
m size = 3

merge

合并另一个multiset。代码示例:

std::multiset m1{1, 1, 1, 2};
std::multiset m2{1, 2, 2, 2};
m1.merge(m2);
std::cout << "m1 size = " << m1.size() << std::endl;

输出结果:

m1 size = 8

查找

count

返回匹配特定元素值的数量。代码示例:

std::multiset m{1, 1, 1, 2, 2};
std::cout << "m key 1 count: " << m.count(1) << std::endl;
std::cout << "m key 2 count: " << m.count(2) << std::endl;

输出结果:

m key 1 count: 3
m key 2 count: 2

find

返回匹配key值的迭代器。代码示例:

std::multiset m{1, 1, 1, 2, 2};
auto iter = m.find(2);
std::cout << "key = " << *iter << std::endl;

输出结果:

key = 2

contains

检查是否包含某个key值,返回布尔值。代码示例:

std::multiset m{1, 1, 1, 2, 2};
std::cout << std::boolalpha;
std::cout << "m contains 1: " << m.contains(1) << std::endl;
std::cout << "m contains 3: " << m.contains(3) << std::endl;

输出结果:

m contains 1: true
m contains 3: false

lower_bound

返回首个大于等于给定键值的迭代器。代码示例:

std::multiset m{2, 3, 5, 7, 11, 13, 17};
auto iter = m.lower_bound(5);
std::cout << "key = " << *iter << std::endl;

输出结果:

key = 5

upper_bound

返回首个大于给定键值的迭代器。代码示例:

std::multiset m{2, 3, 5, 7, 11, 13, 17};
auto iter = m.upper_bound(5);
std::cout << "key = " << *iter << std::endl;

输出结果:

key = 7

equal_range

返回一对迭代器,分别是lower_bound和upper_range的结果。代码示例:

std::multiset m{2, 3, 5, 7, 11, 13, 17};
auto [iter1, iter2] = m.equal_range(5);
std::cout << "iter1 = " << *iter1 << std::endl;
std::cout << "iter2 = " << *iter2 << std::endl;

输出结果:

iter1 = 5
iter2 = 7

观察器

key_comp

返回用于比较key值的函数。代码示例:

std::multiset m;
auto comp = m.key_comp();
std::cout << std::boolalpha;
std::cout << comp(1, 2) << std::endl;

输出结果:

true

value_comp

返回用于比较key值的函数。代码示例:

std::multiset m;
auto comp = m.value_comp();
std::cout << std::boolalpha;
std::cout << comp(1, 2) << std::endl;

输出结果:

true

非成员函数

比较运算符

operator==,!=,<,<=,>,>=用于比较两个multiset。代码示例:

std::multiset m1 = {1, 1, 2};
std::multiset m2 = {1, 1};
std::cout << std::boolalpha;
std::cout << "m1 == m2: " << (m1 == m2) << std::endl;
std::cout << "m1 != m2: " << (m1 != m2) << std::endl;
std::cout << "m1 <  m2: " << (m1 < m2) << std::endl;
std::cout << "m1 <= m2: " << (m1 <= m2) << std::endl;
std::cout << "m1 >  m2: " << (m1 > m2) << std::endl;
std::cout << "m1 >= m2: " << (m1 >= m2) << std::endl;

输出结果:

m1 == m2: false
m1 != m2: true
m1 <  m2: false
m1 <= m2: false
m1 >  m2: true
m1 >= m2: true

swap

交换两个multiset的元素内容。代码示例:

std::multiset m1 = {1, 1, 2};
std::multiset m2 = {1, 1};
std::swap(m1, m2);
std::cout << "m1 size is: " << m1.size() << std::endl;
std::cout << "m2 size is: " << m2.size() << std::endl;

输出结果:

m1 size is: 2
m2 size is: 3

erase_if

删除满足要求的元素。代码示例:

std::multiset s = {1, 1, 2, 3, 4};
std::cout << "s size = " << s.size() << std::endl;
std::erase_if(s,
              [](int a)
              {
                  return a <= 2;
              });
std::cout << "s size = " << s.size() << std::endl;

输出结果:

s size = 5
s size = 2

你可能感兴趣的:(c++标准库基础,c++,开发语言)