C++STL容器 – std::map容器修改、元素操作总结 clear,insert,emplace,erase,swap,merge,extract,insert_or_assign等
std::map是一个排序的关联容器,具有唯一键值特性。其实现底层数据结构为红黑树。在红黑树上的查找、插入、删除操作的算法复杂度为O(logN)。本文将对std::map的有关容器修改的函数进行说明和总结。
1 std::map常见函数
1.1 std::map容器修改操作函数
1.1.1 clear
clear的作用主要是清除std::map中的所有元素。
#include <iostream>
#include <map>
#include <string>
void PrintMap(const std::map<int, std::string>& inMap)
{
std::map<int, std::string>::const_iterator const_iter = inMap.begin();
while (const_iter != inMap.end())
{
std::cout << const_iter->first << " " << const_iter->second << std::endl;
const_iter++;
}
}
int main()
{
std::cout << "original map:" << std::endl;
std::map<int, std::string> myMap;
for (int i = 0; i < 5; ++i)
{
myMap[i] = std::to_string(i);
}
PrintMap(myMap);
std::cout << "modifed map:" << std::endl;
myMap.clear();
PrintMap(myMap);
return 0;
}
结果:
original map:
0 0
1 1
2 2
3 3
4 4
modifed map:
1.1.2 insert
insert的作用主要是向std::map容器中插入元素。
如果容器中未包含插入数据对的键值,则将数据对插入容器中;如果容器中已包含插入数据对的键值,则不将数据对插入容器中。具体区别可查看以下代码:
#include <iostream>
#include <map>
#include <string>
void PrintMap(const std::map<int, std::string>& inMap)
{
std::map<int, std::string>::const_iterator const_iter = inMap.begin();
while (const_iter != inMap.end())
{
std::cout << const_iter->first << " " << const_iter->second << std::endl;
const_iter++;
}
}
int main()
{
std::cout << "original map:" << std::endl;
std::map<int, std::string> myMap;
for (int i = 0; i < 5; ++i)
{
myMap[i] = std::to_string(i);
}
PrintMap(myMap);
std::cout << "modifed map:" << std::endl;
myMap.insert({1,"2"});
PrintMap(myMap);
std::cout << "modifed map:" << std::endl;
myMap.insert({ 6,"6" });
PrintMap(myMap);
return 0;
}
结果:
original map:
0 0
1 1
2 2
3 3
4 4
modifed map:
0 0
1 1
2 2
3 3
4 4
modifed map:
0 0
1 1
2 2
3 3
4 4
6 6
我们在向容器中插入元素时可以使用以下方式:
- 初始化列表
- std::pair
- std::make_pair
- 根据迭代器位置插入
- 其他高级方式,如左值,右值等
通过初始化列表插入
myMap.insert({1,"2"});
myMap.insert({ {1,"a"},{2,"b"} });
通过std::pair插入
myMap.insert(std::pair<int,std::string>(1,"a"));
通过std::make_pair插入
myMap.insert(std::make_pair(1,"a"));
在容器迭代器指定的位置插入
myMap.insert(myMap.begin(), std::make_pair(6,"a"));
1.1.3 insert_or_assign(C++17)
insert_or_assign作用主要是向std::map容器中插入元素,元素是就地构造的,即不执行赋值和移动操作。
insert_or_assign与上述的insert函数不同的是,如果容器中存在于插入数据对相同的键值,则将数据对的值赋值给容器中响应的键值对,覆盖原有键值对中的值;如果容器中不存在插入数据对相同的键值,则插入新的数据对,作用与insert函数一样。
#include <iostream>
#include <map>
#include <string>
#include <iomanip>
void PrintMap(const std::map<int, std::string>& inMap)
{
std::map<int, std::string>::const_iterator const_iter = inMap.begin();
while (const_iter != inMap.end())
{
std::cout << const_iter->first << " " << const_iter->second << std::endl;
const_iter++;
}
}
int main()
{
std::cout << "original map:" << std::endl;
std::map<int, std::string> myMap;
for (int i = 0; i < 5; ++i)
{
myMap[i] = std::to_string(i);
}
PrintMap(myMap);
std::cout << "modifed map:" << std::endl;
myMap.insert_or_assign(1, "a");
PrintMap(myMap);
return 0;
}
结果:
original map:
0 0
1 1
2 2
3 3
4 4
modifed map:
0 0
1 a
2 2
3 3
4 4
1.1.4 emplace(C++11)
emplace函数主要作用是如果容器中没有相同键的元素,则将新元素就地构造插入到容器中。
#include <iostream>
#include <map>
#include <string>
#include <iomanip>
void PrintMap(const std::map<int, std::string>& inMap)
{
std::map<int, std::string>::const_iterator const_iter = inMap.begin();
while (const_iter != inMap.end())
{
std::cout << const_iter->first << " " << const_iter->second << std::endl;
const_iter++;
}
}
int main()
{
std::cout << "original map:" << std::endl;
std::map<int, std::string> myMap;
for (int i = 0; i < 5; ++i)
{
myMap[i] = std::to_string(i);
}
PrintMap(myMap);
std::cout << "modifed map:" << std::endl;
myMap.emplace(6, "a");
PrintMap(myMap);
return 0;
}
结果:
original map:
0 0
1 1
2 2
3 3
4 4
modifed map:
0 0
1 1
2 2
3 3
4 4
6 a
也可通过以下方式进行插入:
- std::pair
- std::make_pair
使用std::pair进行emplace
myMap.emplace(std::pair<int,std::string>(6,"a"));
使用std::make_pair进行emplace
myMap.emplace(std::make_pair(6,"a"));
1.1.5 emplace_hint(C++11)
1.1.6 try_emplace(C++17)
try_emplace函数主要作用是如果容器中没有相同键的元素,则将新元素插入到容器中,其新元素使用给定的args构造。
#include <iostream>
#include <map>
#include <string>
#include <iomanip>
void PrintMap(const std::map<int, std::string>& inMap)
{
std::map<int, std::string>::const_iterator const_iter = inMap.begin();
while (const_iter != inMap.end())
{
std::cout << const_iter->first << " " << const_iter->second << std::endl;
const_iter++;
}
}
int main()
{
std::cout << "original map:" << std::endl;
std::map<int, std::string> myMap;
for (int i = 0; i < 5; ++i)
{
myMap[i] = std::to_string(i);
}
PrintMap(myMap);
std::cout << "modifed map:" << std::endl;
myMap.try_emplace(6,"a");
PrintMap(myMap);
std::cout << "modifed map:" << std::endl;
myMap.try_emplace(6, "b");
PrintMap(myMap);
return 0;
}
结果:
original map
0 0
1 1
2 2
3 3
4 4
modifed map:
0 0
1 1
2 2
3 3
4 4
6 a
modifed map:
0 0
1 1
2 2
3 3
4 4
6 a
1.1.7 erase
erase函数的作用主要是从std::map中移除指定的元素。
#include <iostream>
#include <map>
#include <string>
#include <iomanip>
void PrintMap(const std::map<int, std::string>& inMap)
{
std::map<int, std::string>::const_iterator const_iter = inMap.begin();
while (const_iter != inMap.end())
{
std::cout << const_iter->first << " " << const_iter->second << std::endl;
const_iter++;
}
}
int main()
{
std::cout << "original map:" << std::endl;
std::map<int, std::string> myMap;
for (int i = 0; i < 5; ++i)
{
myMap[i] = std::to_string(i);
}
PrintMap(myMap);
std::cout << "modifed map:" << std::endl;
for (auto iter = myMap.begin(); iter != myMap.end();)
{
if (iter->first == 2)
{
iter = myMap.erase(iter);
}
else
{
iter++;
}
}
PrintMap(myMap);
return 0;
}
结果:
original map:
0 0
1 1
2 2
3 3
4 4
modifed map:
0 0
1 1
3 3
4 4
1.1.8 swap
swap函数的作用主要是与其它容器的内容进行对换。
#include <iostream>
#include <string>
#include <utility>
#include <map>
// print out a std::pair
template <class Os, class U, class V>
Os& operator<<(Os& os, const std::pair<U, V>& p) {
return os << p.first << ":" << p.second;
}
// print out a container
template <class Os, class Co>
Os& operator<<(Os& os, const Co& co) {
os << "{";
for (auto const& i : co) { os << ' ' << i; }
return os << " }\n";
}
int main()
{
std::map<std::string, std::string>
m1 { {"γ", "gamma"}, {"β", "beta"}, {"α", "alpha"}, {"γ", "gamma"}, },
m2 { {"ε", "epsilon"}, {"δ", "delta"}, {"ε", "epsilon"} };
const auto& ref = *(m1.begin());
const auto iter = std::next(m1.cbegin());
std::cout << "──────── before swap ────────\n"
<< "m1: " << m1 << "m2: " << m2 << "ref: " << ref
<< "\niter: " << *iter << '\n';
m1.swap(m2);
std::cout << "──────── after swap ────────\n"
<< "m1: " << m1 << "m2: " << m2 << "ref: " << ref
<< "\niter: " << *iter << '\n';
// Note that every iterator referring to an element in one container before
// the swap refers to the same element in the other container after the swap.
// Same is true for references.
}
结果:
──────── before swap ────────
m1: { α:alpha β:beta γ:gamma }
m2: { δ:delta ε:epsilon }
ref: α:alpha
iter: β:beta
──────── after swap ────────
m1: { δ:delta ε:epsilon }
m2: { α:alpha β:beta γ:gamma }
ref: α:alpha
iter: β:beta
1.1.9 extract(C++17)
extract函数的作用主要是将给定位置或者给定键值的元素节点取消在当前容器中的链接,并返回该元素的节点句柄。如果没有给定键值的元素,则返回空的节点句柄。此操作不会复制或者拷贝元素,只是重新调整容器内部的节点指针指向。extract函数只会使得当前提取的元素的迭代器无效,提取元素的指针和引用仍然有效,但在元素由节点句柄拥有时不能使用:如果元素被插入容器,它们将变得可用。
#include <algorithm>
#include <iostream>
#include <map>
int main()
{
std::map<int, char> cont{{1, 'a'}, {2, 'b'}, {3, 'c'}};
auto print = [](std::pair<const int, char>& n) {
std::cout << " " << n.first << '(' << n.second << ')';
};
std::cout << "Start:";
std::for_each(cont.begin(), cont.end(), print);
std::cout << '\n';
// Extract node handle and change key
auto nh = cont.extract(1);
nh.key() = 4;
std::cout << "After extract and before insert:";
std::for_each(cont.begin(), cont.end(), print);
std::cout << '\n';
// Insert node handle back
cont.insert(move(nh));
std::cout << "End:";
std::for_each(cont.begin(), cont.end(), print);
std::cout << '\n';
}
结果:
Start: 1(a) 2(b) 3(c)
After extract and before insert: 2(b) 3(c)
End: 2(b) 3(c) 4(a)
1.1.10 merge(C++17)
merge函数的作用主要是将输入容器的所有元素重新合并到当前容器中,如果输入容器中有与当前容器键值相同元素,则不进行合并。在这一过程中没有元素拷贝和移动操作,只是要合并的元素从输入容器指向当前容器。
#include <map>
#include <iostream>
#include <string>
int main()
{
std::map<int, std::string> ma {{1, "apple"}, {5, "pear"}, {10, "banana"}};
std::map<int, std::string> mb {{2, "zorro"}, {4, "batman"}, {5, "X"}, {8, "alpaca"}};
std::map<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
本文作者:StubbornHuang
版权声明:本文为站长原创文章,如果转载请注明原文链接!
原文标题:C++STL容器 – std::map容器修改、元素操作总结 clear,insert,emplace,erase,swap,merge,extract,insert_or_assign等
原文链接:https://www.stubbornhuang.com/1992/
发布于:2022年03月01日 14:19:04
修改于:2023年06月26日 20:33:20
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。
评论
50