序列式容器:
序列式容器是一组用于存储数据的容器,其中的数据按照它们在容器中的位置进行存储和访问。序列式容器提供了对元素的线性访问和操作,其主要特点包括:
C++标准库中的序列式容器包括 std::vector
、std::deque
、std::list
、std::array
等。这些容器适用于需要按顺序处理数据的情况,如数组、列表、队列等。
总结:
关联式容器:
关联式容器是一组用于存储数据的容器,其中的数据按照某种规则关联起来,通常是基于键值的关联。关联式容器提供了一种高效的方式来查找、插入和删除元素,其主要特点包括:
C++标准库中的关联式容器包括 std::set
、std::multiset
、std::map
、std::multimap
等。这些容器适用于需要高效查找和排序的情况,如字典、集合等。
用来表示具有一一对应关系的一种结构,该结构中一般只包含两个成员变量key
和value
,key
代表键值,value
表示与key
对应的信息。比如:现在要建立一个英汉互译的字典,那该字典中必然有英文单词与其对应的中文含义,而且,英文单词与其中文含义是一一对应的关系,即通过该应该单词,在词典中就可以找到与其对应的中文含义
SGI-STL中关于键值对的定义
template <class T1, class T2>
struct pair
{
typedef T1 first_type;
typedef T2 second_type;
T1 first;
T2 second;
pair(): first(T1()), second(T2())
{}
pair(const T1& a, const T2& b): first(a), second(b)
{}
};
根据应用场景的不同,STL总共实现了两种不同结构的管理式容器:树型结构与哈希结构
C++标准库提供了四种主要的树形结构关联式容器,它们分别是 std::set
、std::multiset
、std::map
和 std::multimap
。这些容器都是基于树的数据结构,通常使用红黑树实现,用于存储键值对,并提供高效的查找和排序功能。以下是对这四种容器的详细解释:
std::set
是一个集合容器,它存储唯一的键值(key),不允许重复的键。insert
、erase
、find
等操作来管理元素集合。std::multiset
与 std::set
类似,但允许存储重复的键值。因此,它可以包含相同的键多次。insert
、erase
、find
等操作。std::map
是一个键值对容器,每个键都唯一对应一个值。insert
、erase
、find
等操作来管理键值对。std::multimap
与 std::map
类似,但允许存储相同的键对应不同的值,因此一个键可以对应多个值。insert
、erase
、find
等操作。这些容器的共同特点是它们的元素是按照键值有序存储的,这使得它们适用于需要快速查找和自动排序的情况。它们使用平衡二叉树(通常是红黑树)来实现这些功能,保持了插入、删除和查找的平均时间复杂度为 O(log N)
。
选择哪种容器取决于需求。如果需要存储唯一的键或键值对,可以选择 std::set
或 std::map
。如果需要允许重复的键或键对应多个值,可以选择 std::multiset
或 std::multimap
。这些容器提供了丰富的操作,可以满足各种数据组织和访问的需求。
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(class T)
:这是模板的第一个参数,表示存储在set
容器中的元素的数据类型。set
会存储类型为T
的元素。Compare(class Compare = less)
:这是模板的第二个参数,表示用于比较元素之间的顺序的比较函数。默认情况下,它采用less
,它使用元素的小于运算符<
来进行比较。您可以提供自定义的比较函数,以定义元素之间的排序规则。这个比较函数必须是一个可调用的二元谓词,它接受两个参数(const T&
类型)并返回一个bool
值,指示它们的顺序。Alloc(class Alloc = allocator)
:这是模板的第三个参数,表示用于分配和管理内存的分配器类型。默认情况下,它采用std::allocator
,这是C++标准库提供的分配器。您可以提供自定义的分配器类型,以满足特定的内存管理需求。std::set
是一个有序容器,它以红黑树(Red-Black Tree)作为底层数据结构来存储元素。红黑树是一种自平衡二叉搜索树,保持了元素的有序性,并且允许高效的插入、删除和查找操作。std::set
中的元素是唯一的,即相同的元素只会被存储一次。
成员类型
关于C++标准库中std::set
容器构造函数的不同形式和重载,以及它们的用途的解释:
explicit set (const key_compare& comp = key_compare(), const allocator_type& alloc = allocator_type());
:
std::set
容器。comp
用于指定比较函数,它用于确定元素的顺序。默认情况下,使用key_compare()
,即容器类型中指定的比较函数。alloc
用于指定分配器,用于管理内存。默认情况下,使用allocator_type()
,即容器类型中指定的分配器。#include
#include
int main() {
// 使用默认构造函数创建一个空的 set
std::set<int> mySet;
// 向 set 中插入元素
mySet.insert(5);
mySet.insert(2);
mySet.insert(8);
// 输出 set 的内容
for (const int& value : mySet) {
std::cout << value << " ";
}
std::cout << std::endl;
return 0;
}
template
:
std::set
容器,并初始化其内容,从范围 [first, last)
中的元素。first
和last
是迭代器,用于指定范围。容器将包含该范围内的元素。comp
和alloc
与默认构造函数中的含义相同,用于指定比较函数和分配器。#include
#include
#include
int main() {
// 创建一个包含 vector 中元素的 set
std::vector<int> vec = {3, 1, 4, 1, 5, 9};
std::set<int> mySet(vec.begin(), vec.end());
// 输出 set 的内容
for (const int& value : mySet) {
std::cout << value << " ";
}
std::cout << std::endl;
return 0;
}
set (const set& x);
:
std::set
容器,并使用另一个set
容器x
的内容初始化它。x
中的所有元素复制到新容器中。#include
#include
int main() {
// 创建一个 set 并初始化
std::set<int> set1 = {1, 2, 3};
// 使用拷贝构造函数创建一个新的 set,复制 set1 的内容
std::set<int> set2(set1);
// 输出 set2 的内容
for (const int& value : set2) {
std::cout << value << " ";
}
std::cout << std::endl;
return 0;
}
这些构造函数提供了不同的方式来初始化和创建std::set
容器,以适应不同的需求。您可以根据需要选择适当的构造函数来创建和初始化std::set
容器,以存储和管理数据。
赋值运算符重载
set& operator= (const set& x);
是C++标准库中std::set
容器的赋值运算符(operator=
)重载函数的签名。
这个赋值运算符用于将一个std::set
容器的内容复制给另一个std::set
容器。具体来说,它将右操作数(x
,另一个std::set
容器)的内容复制到左操作数(调用该运算符的std::set
容器)中,并返回左操作数的引用。
下面是赋值运算符的使用示例:
std::set<int> set1 = {1, 2, 3};
std::set<int> set2;
// 使用赋值运算符将 set1 的内容复制到 set2
set2 = set1;
// 现在 set2 包含了 set1 的内容
在上面的示例中,set2 = set1
使用赋值运算符将set1
的内容复制到set2
,使得set2
包含了与set1
相同的元素。
需要注意的是,赋值运算符会删除左操作数原来的内容,并用右操作数的内容替代它。这意味着在赋值之后,左操作数的内容将与右操作数相同,而原来的内容将被销毁。
这个赋值运算符对于将一个std::set
容器的内容复制到另一个容器非常有用,可以用于容器之间的数据交换和拷贝。
这些函数是C++标准库中std::set
容器的成员函数,用于获取不同类型的迭代器和常量迭代器,以便遍历std::set
容器的元素。以下是这些迭代器和常量迭代器的描述:
std::set
容器中第一个元素的位置。std::set
容器中超出最后一个元素的位置。std::set
容器中最后一个元素的位置。使用反向迭代器可以逆序遍历容器。std::set
容器中超出第一个元素的位置。它通常与rbegin
一起使用,以定义逆序遍历的结束点。std::set
容器中第一个元素的位置。常量迭代器用于遍历容器并防止修改容器中的元素。std::set
容器中超出最后一个元素的位置。std::set
容器中最后一个元素的位置。常量反向迭代器用于逆序遍历容器,并防止修改容器中的元素。std::set
容器中超出第一个元素的位置。通常与crbegin
一起使用,以定义逆序遍历的结束点。示例:
#include
#include
int main() {
// 创建一个 std::set 容器并初始化
std::set<int> mySet = {5, 2, 8, 1, 9};
// 使用 begin 和 end 迭代器遍历容器
std::cout << "正序遍历:" << std::endl;
for (std::set<int>::iterator it = mySet.begin(); it != mySet.end(); ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;
// 使用 rbegin 和 rend 反序遍历容器
std::cout << "逆序遍历:" << std::endl;
for (std::set<int>::reverse_iterator rit = mySet.rbegin(); rit != mySet.rend(); ++rit) {
std::cout << *rit << " ";
}
std::cout << std::endl;
// 使用 cbegin 和 cend 常量迭代器遍历容器
std::cout << "使用常量迭代器:" << std::endl;
for (std::set<int>::const_iterator cit = mySet.cbegin(); cit != mySet.cend(); ++cit) {
std::cout << *cit << " ";
}
std::cout << std::endl;
// 使用 crbegin 和 crend 常量反序遍历容器
std::cout << "使用常量反序迭代器:" << std::endl;
for (std::set<int>::const_reverse_iterator crit = mySet.crbegin(); crit != mySet.crend(); ++crit) {
std::cout << *crit << " ";
}
std::cout << std::endl;
return 0;
}
输出:
正序遍历:
1 2 5 8 9
逆序遍历:
9 8 5 2 1
使用常量迭代器:
1 2 5 8 9
使用常量反序迭代器:
9 8 5 2 1
这个示例演示了如何使用不同类型的迭代器来遍历std::set
容器中的元素。正序遍历使用begin
和end
迭代器,逆序遍历使用rbegin
和rend
反向迭代器,常量迭代器使用cbegin
和cend
,常量反序迭代器使用crbegin
和crend
。这些迭代器允许您以不同的方式访问容器中的元素,并提供了对元素的只读访问(对于常量迭代器)或读写访问(对于非常量迭代器)
这里是关于C++标准库中std::set
容器的容量相关成员函数的解释和示例:
empty(测试容器是否为空):
bool empty() const
是一个公有成员函数,用于测试容器是否为空。true
;否则,返回 false
。示例:
std::set<int> mySet;
if (mySet.empty()) {
std::cout << "容器为空" << std::endl;
} else {
std::cout << "容器不为空" << std::endl;
}
size(返回容器大小):
size_type size() const
是一个公有成员函数,用于返回容器中元素的数量。size_type
),表示容器中元素的个数。示例:
std::set<int> mySet = {1, 2, 3, 4, 5};
std::cout << "容器的大小为: " << mySet.size() << std::endl;
max_size(返回最大可能大小):
size_type max_size() const
是一个公有成员函数,用于返回容器的最大可能大小。size_type
),表示容器可以容纳的最大元素数量,这取决于系统和编译器。示例:
std::set<int> mySet;
std::cout << "容器的最大可能大小为: " << mySet.max_size() << std::endl;
这些容量相关的成员函数允许您查询容器的状态,例如检查容器是否为空、获取容器的大小以及了解容器可以容纳的最大元素数量。这对于在使用容器时进行状态检查和资源规划非常有用。
std::set
容器的修改器(Modifiers)相关成员函数,它们用于修改std::set
容器的内容:
std::pair insert(const value_type& val);
iterator insert(iterator position, const value_type& val);
template void insert(InputIterator first, InputIterator last);
std::set
容器中插入元素。它们允许插入单个元素或一组元素。insert
函数返回一个迭代器指向插入的元素(或已存在的元素),以及一个bool
值指示是否插入成功。iterator erase(iterator position);
size_type erase(const key_type& key);
iterator erase(iterator first, iterator last);
std::set
容器中删除元素。您可以提供要删除的元素的位置或键(key)。erase
函数返回一个迭代器,指向被删除元素之后的位置。void swap(set& x);
std::set
容器的内容,使它们互相包含对方的元素。void clear();
template pair emplace(Args&&... args);
bool
值指示是否插入成功。template iterator emplace_hint(iterator position, Args&&... args);
emplace
类似,但允许提供一个插入位置的提示(iterator position),以便更高效地插入新元素。示例:
#include
#include
int main() {
// 创建一个 std::set 容器并初始化
std::set<int> mySet = {5, 2, 8, 1, 9};
// 输出容器的内容
std::cout << "容器的内容:";
for (const int& value : mySet) {
std::cout << " " << value;
}
std::cout << std::endl;
// 使用 insert 插入元素
std::pair<std::set<int>::iterator, bool> result1 = mySet.insert(3); // 插入元素3
std::pair<std::set<int>::iterator, bool> result2 = mySet.insert(5); // 尝试插入重复元素5
if (result1.second) {
std::cout << "成功插入元素3" << std::endl;
} else {
std::cout << "元素3已存在" << std::endl;
}
if (result2.second) {
std::cout << "成功插入元素5" << std::endl;
} else {
std::cout << "元素5已存在" << std::endl;
}
// 输出修改后的容器内容
std::cout << "修改后的容器内容:";
for (const int& value : mySet) {
std::cout << " " << value;
}
std::cout << std::endl;
// 使用 erase 删除元素
mySet.erase(2); // 删除元素2
// 输出删除元素后的容器内容
std::cout << "删除元素后的容器内容:";
for (const int& value : mySet) {
std::cout << " " << value;
}
std::cout << std::endl;
// 使用 emplace 插入元素(构造并插入)
mySet.emplace(6); // 插入元素6
// 输出插入元素后的容器内容
std::cout << "插入元素后的容器内容:";
for (const int& value : mySet) {
std::cout << " " << value;
}
std::cout << std::endl;
return 0;
}
输出:
容器的内容: 1 2 5 8 9
成功插入元素3
元素5已存在
修改后的容器内容: 1 2 3 5 8 9
删除元素后的容器内容: 1 3 5 8 9
插入元素后的容器内容: 1 3 5 6 8 9
Observers
key_compare key_comp() const;
value_compare value_comp() const;
Operations
iterator find(const key_type& key);
end()
。size_type count(const key_type& key);
iterator lower_bound(const key_type& key);
iterator upper_bound(const key_type& key);
pair equal_range(const key_type& key);
pair
,第一个迭代器指向第一个等于给定键的元素,第二个迭代器指向第一个大于给定键的元素。示例:
#include
#include
int main() {
std::set<int> mySet = {1, 2, 3, 4, 5};
// 使用 key_comp 获取键的比较对象
std::set<int>::key_compare keyComp = mySet.key_comp();
// 使用 value_comp 获取值的比较对象
std::set<int>::value_compare valueComp = mySet.value_comp();
// 查找元素
std::set<int>::iterator it = mySet.find(3);
if (it != mySet.end()) {
std::cout << "找到元素 3" << std::endl;
} else {
std::cout << "未找到元素 3" << std::endl;
}
// 计算特定值的元素个数
size_t count = mySet.count(4);
std::cout << "值为 4 的元素个数: " << count << std::endl;
// 获取下限迭代器
std::set<int>::iterator lower = mySet.lower_bound(2);
std::cout << "下限迭代器指向大于或等于 2 的元素位置: " << *lower << std::endl;
// 获取上限迭代器
std::set<int>::iterator upper = mySet.upper_bound(4);
std::cout << "上限迭代器指向大于 4 的元素位置: " << *upper << std::endl;
// 获取相等元素的范围
std::pair<std::set<int>::iterator, std::set<int>::iterator> range = mySet.equal_range(3);
std::cout << "相等元素范围: [" << *(range.first) << ", " << *(range.second) << "]" << std::endl;
return 0;
}
#include
void TestSet()
{
// 用数组array中的元素构造set
int array[] = { 1, 3, 5, 7, 9, 2, 4, 6, 8, 0, 1, 3, 5, 7, 9, 2, 4,6, 8, 0 };
set<int> s(array, array+sizeof(array)/sizeof(array));
cout << s.size() << endl;
// 正向打印set中的元素,从打印结果中可以看出:set可去重
for (auto& e : s)
cout << e << " ";
cout << endl;
// 使用迭代器逆向打印set中的元素
for (auto it = s.rbegin(); it != s.rend(); ++it)
cout << *it << " ";
cout << endl;
// set中值为3的元素出现了几次
cout << s.count(3) << endl;
}
std::set
和 std::multiset
都是 C++ 标准库中的关联式容器,它们用于存储一组元素,且元素是按照一定的顺序排列的。然而,它们之间有一个关键的区别:
std::set
:std::set
中的元素是唯一的,不允许重复的元素存在。如果试图插入重复的元素,新元素将不会被插入。std::multiset
:std::multiset
允许存储重复的元素,可以插入多个具有相同键值的元素。下面是更详细的比较:
O(log n)
的时间内完成,因为元素唯一。O(log n)
的时间内完成,因为仍然具有排序特性。multiset
在底层实际存储的是
的键值对。在选择使用 std::set
还是 std::multiset
时,取决于你的数据需求。如果需要维护一组唯一的值,使用 std::set
;如果允许重复值,并且需要统计重复值的出现次数,使用 std::multiset
。
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;
std::map
是一个关联式容器,它提供了key-value
对的存储和管理。以下是代码中各个模板参数的解释:
Key
:表示std::map
容器中的键类型,也就是键值对中的键的类型。T
:表示std::map
容器中的值类型,也就是键值对中的值的类型。Compare
:表示比较键的方式的函数对象,默认使用 std::less
,可以根据需要自定义键的比较方式。Alloc
:表示用于分配内存的分配器类型,默认使用 std::allocator>
,通常情况下不需要自定义。通过这个模板声明,你可以创建不同类型的std::map
容器,以存储不同类型的key-value
对。例如,如果要创建一个存储整数键和字符串值的std::map
容器,可以这样使用:
std::map<int, std::string> myMap;
这将创建一个std::map
容器,其中键的类型是整数 (int
),值的类型是字符串 (std::string
)。您可以使用该容器来存储和检索整数和字符串之间的映射关系。
成员类型
explicit map(const key_compare& comp = key_compare(), const allocator_type& alloc = allocator_type());
std::map
的默认构造函数,它创建一个空的std::map
对象。comp
参数是可选的,表示用于比较键的自定义比较函数,默认使用 key_compare()
,即使用std::less
。alloc
参数是可选的,表示用于内存分配的自定义分配器,默认使用 allocator_type()
,即使用std::allocator>
。template map(InputIterator first, InputIterator last, const key_compare& comp = key_compare(), const allocator_type& alloc = allocator_type());
first
和 last
定义)初始化std::map
容器。comp
参数是可选的,表示用于比较键的自定义比较函数,默认使用 key_compare()
。alloc
参数是可选的,表示用于内存分配的自定义分配器,默认使用 allocator_type()
。map(const map& x);
std::map
容器,并以另一个std::map
容器 x
的内容进行初始化,即复制x
中的键值对到新的容器中。示例:
#include
#include
int main() {
// 使用默认构造函数创建一个空的 std::map
std::map<int, std::string> myMap1;
// 使用范围构造函数创建并初始化 std::map
std::map<int, std::string> myMap2 = {{1, "One"}, {2, "Two"}, {3, "Three"}};
// 使用复制构造函数创建一个与 myMap2 相同内容的副本
std::map<int, std::string> myMap3(myMap2);
// 输出容器内容
std::cout << "myMap1: " << myMap1.size() << " elements" << std::endl;
std::cout << "myMap2: " << myMap2.size() << " elements" << std::endl;
std::cout << "myMap3: " << myMap3.size() << " elements" << std::endl;
return 0;
}
在此示例中,我们演示了三种不同的std::map
构造函数的使用方式,包括默认构造函数、范围构造函数和复制构造函数。根据构造函数的不同用途,可以创建空容器、初始化容器或复制另一个容器的内容。
赋值运算符重载
将一个 std::map
的内容复制到另一个已存在的 std::map
中。例如:
std::map<int, std::string> sourceMap = {{1, "One"}, {2, "Two"}};
std::map<int, std::string> targetMap;
targetMap = sourceMap; // 使用拷贝赋值运算符将内容复制到目标容器
它会创建一个新的 std::map
容器,其中包含与原始容器相同的键值对。这是一种将数据从一个容器复制到另一个容器的常见方式。
std::map
容器提供了多种迭代器,用于访问容器中的元素。以下是这些迭代器的详细描述:
iterator begin();
std::map
容器中第一个元素的位置。iterator end();
std::map
容器中的末尾(尾后位置)。reverse_iterator rbegin();
std::map
容器中的最后一个元素的位置。reverse_iterator rend();
std::map
容器中的逆向末尾(逆向尾后位置)。const_iterator cbegin() const;
std::map
容器中第一个元素的位置。用于只读访问。const_iterator cend() const;
std::map
容器中的末尾(尾后位置)。用于只读访问。const_reverse_iterator crbegin() const;
std::map
容器中的最后一个元素的位置。用于只读访问。const_reverse_iterator crend() const;
std::map
容器中的逆向末尾(逆向尾后位置)。用于只读访问。示例:
#include
#include
int main() {
// 创建一个 std::map 容器并初始化
std::map<int, std::string> myMap = {{1, "One"}, {2, "Two"}, {3, "Three"}};
// 使用正向迭代器遍历容器
std::cout << "正向迭代器遍历容器:" << std::endl;
for (std::map<int, std::string>::iterator it = myMap.begin(); it != myMap.end(); ++it) {
std::cout << "键: " << it->first << ", 值: " << it->second << std::endl;
}
// 使用逆向迭代器遍历容器
std::cout << "逆向迭代器遍历容器:" << std::endl;
for (std::map<int, std::string>::reverse_iterator rit = myMap.rbegin(); rit != myMap.rend(); ++rit) {
std::cout << "键: " << rit->first << ", 值: " << rit->second << std::endl;
}
// 使用常量迭代器遍历容器(只读访问)
std::cout << "常量迭代器遍历容器:" << std::endl;
for (std::map<int, std::string>::const_iterator cit = myMap.cbegin(); cit != myMap.cend(); ++cit) {
std::cout << "键: " << cit->first << ", 值: " << cit->second << std::endl;
}
// 使用常量逆向迭代器遍历容器(只读访问)
std::cout << "常量逆向迭代器遍历容器:" << std::endl;
for (std::map<int, std::string>::const_reverse_iterator crit = myMap.crbegin(); crit != myMap.crend(); ++crit) {
std::cout << "键: " << crit->first << ", 值: " << crit->second << std::endl;
}
return 0;
}
这个示例演示了如何使用不同类型的迭代器遍历std::map
容器中的元素:
begin()
和 end()
遍历容器。rbegin()
和 rend()
逆向遍历容器。cbegin()
和 cend()
以只读方式遍历容器。crbegin()
和 crend()
以只读方式逆向遍历容器。这些是关于std::map
容器的一些容量和元素访问相关的成员函数:
bool empty() const;
std::map
容器是否为空。如果容器为空,返回true
;否则返回false
。size_type size() const;
std::map
容器中键值对的数量,也就是容器的大小。size_type max_size() const;
std::map
容器可以容纳的最大元素数量。这通常受到系统内存限制的影响。T& operator[](const key_type& key);
T& at(const key_type& key);
operator[]
。但与 operator[]
不同,如果键不存在,at
会抛出 std::out_of_range
异常。示例:
#include
#include
int main() {
std::map<int, std::string> myMap = {{1, "One"}, {2, "Two"}, {3, "Three"}};
// 检查容器是否为空
if (myMap.empty()) {
std::cout << "容器为空" << std::endl;
} else {
std::cout << "容器不为空" << std::endl;
}
// 获取容器的大小
std::cout << "容器大小为: " << myMap.size() << std::endl;
// 访问容器中的元素
std::string value = myMap[2]; // 使用 operator[]
std::cout << "键 2 对应的值为: " << value << std::endl;
try {
std::string value = myMap.at(4); // 键 4 不存在,会抛出异常
} catch (const std::out_of_range& e) {
std::cerr << "键 4 不存在: " << e.what() << std::endl;
}
return 0;
}
在此示例中,我们演示了如何使用std::map
容器的容量和元素访问成员函数,包括检查容器是否为空、获取容器大小、通过键访问元素以及处理键不存在的情况。
pair insert(const value_type& value);
value_type
)到std::map
容器中。如果插入成功,返回一个迭代器指向插入的元素和 true
;如果元素已存在,则返回一个迭代器指向现有元素和 false
。iterator erase(iterator position);
size_type erase(const key_type& key);
position
指定的元素,并返回指向下一个元素的迭代器。第二种形式删除指定键的元素,并返回删除的元素数量。void swap(map& x);
std::map
容器的内容,即交换键值对。交换后,两个容器的内容完全交换。void clear();
std::map
容器中的所有元素,使容器成为空容器。pair emplace(Args&&... args);
Args
是键值对的构造参数。如果插入成功,返回一个迭代器指向插入的元素和 true
;如果元素已存在,则返回一个迭代器指向现有元素和 false
。iterator emplace_hint(const_iterator position, Args&&... args);
Args
是键值对的构造参数,并且可以提供插入位置的提示。返回一个迭代器指向插入的元素。示例:
#include
#include
int main() {
std::map<int, std::string> myMap;
// 插入元素
myMap.insert(std::make_pair(1, "One"));
myMap.insert(std::make_pair(2, "Two"));
// 删除元素
myMap.erase(2);
// 交换容器内容
std::map<int, std::string> anotherMap = {{3, "Three"}, {4, "Four"}};
myMap.swap(anotherMap);
// 清空容器
myMap.clear();
// 构造并插入元素
myMap.emplace(5, "Five");
// 使用 emplace_hint 插入元素
std::map<int, std::string>::iterator it = myMap.emplace_hint(myMap.begin(), 6, "Six");
// 输出容器内容
for (const auto& pair : myMap) {
std::cout << "键: " << pair.first << ", 值: " << pair.second << std::endl;
}
return 0;
}
在此示例中,我们演示了如何使用std::map
容器的修改器成员函数,包括插入、删除、交换和清空元素,以及使用 emplace
和 emplace_hint
插入元素的方式。
Observers
key_compare key_comp() const;
value_compare value_comp() const;
Operations
iterator find(const key_type& key);
end()
。size_type count(const key_type& key);
iterator lower_bound(const key_type& key);
iterator upper_bound(const key_type& key);
pair equal_range(const key_type& key);
pair
,第一个迭代器指向第一个等于给定键的元素,第二个迭代器指向第一个大于给定键的元素。以下是示例用法:
#include
#include
int main() {
std::map<int, std::string> myMap = {{1, "One"}, {2, "Two"}, {3, "Three"}};
// 使用 find 查找元素
std::map<int, std::string>::iterator it = myMap.find(2);
if (it != myMap.end()) {
std::cout << "找到键 2,值为: " << it->second << std::endl;
} else {
std::cout << "未找到键 2" << std::endl;
}
// 使用 count 计算特定键的元素个数
size_t count = myMap.count(3);
std::cout << "键 3 的元素个数: " << count << std::endl;
// 使用 lower_bound 获取下限迭代器
std::map<int, std::string>::iterator lower = myMap.lower_bound(2);
std::cout << "下限迭代器指向键 2,值为: " << lower->second << std::endl;
// 使用 upper_bound 获取上限迭代器
std::map<int, std::string>::iterator upper = myMap.upper_bound(2);
std::cout << "上限迭代器指向大于键 2 的元素,值为: " << upper->second << std::endl;
// 使用 equal_range 获取相等元素的范围
std::pair<std::map<int, std::string>::iterator, std::map<int, std::string>::iterator> range = myMap.equal_range(2);
std::cout << "相等元素范围: [" << range.first->second << ", " << range.second->second << "]" << std::endl;
return 0;
}
在此示例中,我们演示了如何使用std::map
容器的观察器和操作成员函数,包括查找元素、计算特定键的元素个数、获取下限迭代器、获取上限迭代器以及获取相等元素的范围。这些函数使得在std::map
容器中执行查找和搜索操作变得非常方便。
#include
#include
void TestMap()
{
map<string, string> m;
// 向map中插入元素的方式:
// 将键值对<"peach","桃子">插入map中,用pair直接来构造键值对
m.insert(pair<string, string>("peach", "桃子"));
// 将键值对<"peach","桃子">插入map中,用make_pair函数来构造键值对
m.insert(make_pair("banan", "香蕉"));
// 借用operator[]向map中插入元素
/*
operator[]的原理是:
用构造一个键值对,然后调用insert()函数将该键值对插入到map中
如果key已经存在,插入失败,insert函数返回该key所在位置的迭代器
如果key不存在,插入成功,insert函数返回新插入元素所在位置的迭代器
operator[]函数最后将insert返回值键值对中的value返回
*/
// 将<"apple", "">插入map中,插入成功,返回value的引用,将“苹果”赋值给该引用结果,
m["apple"] = "苹果";
// key不存在时抛异常
//m.at("waterme") = "水蜜桃";
cout << m.size() << endl;
// 用迭代器去遍历map中的元素,可以得到一个按照key排序的序列
for (auto& e : m)
cout << e.first << "--->" << e.second << endl;
cout << endl;
// map中的键值对key一定是唯一的,如果key存在将插入失败
auto ret = m.insert(make_pair("peach", "桃色"));
if (ret.second)
cout << "不在map中, 已经插入" << endl;
else
cout << "键值为peach的元素已经存在:" << ret.first->first << "--->"
<< ret.first->second << " 插入失败" << endl;
// 删除key为"apple"的元素
m.erase("apple");
if (1 == m.count("apple"))
cout << "apple还在" << endl;
else
cout << "apple被吃了" << endl;
}
std::map
和 std::multimap
都是 C++ 标准库中的关联式容器,它们用于存储一组key-value
对(键值对),并根据键对元素进行排序。它们之间的主要区别在于唯一性和允许重复性:
std::map:
std::map
是一个关联容器,其中的键是唯一的,每个键只能关联一个值。operator[]
或 insert
插入元素。find
、count
、lower_bound
、upper_bound
)返回匹配的唯一元素。std::multimap:
std::multimap
也是一个关联容器,允许多个具有相同键的值存在。insert
插入元素。以下是示例用法和比较:
std::map 示例:
#include
#include
int main() {
std::map<int, std::string> myMap;
// 插入键值对
myMap[1] = "One";
myMap[2] = "Two";
myMap[3] = "Three";
// 重复键值对将覆盖旧值
myMap[2] = "New Two";
// 查找键为 2 的元素
std::map<int, std::string>::iterator it = myMap.find(2);
if (it != myMap.end()) {
std::cout << "找到键 2,值为: " << it->second << std::endl;
}
return 0;
}
std::multimap 示例:
#include
#include
int main() {
std::multimap<int, std::string> myMultiMap;
// 插入多个具有相同键的值
myMultiMap.insert(std::make_pair(1, "One"));
myMultiMap.insert(std::make_pair(2, "Two"));
myMultiMap.insert(std::make_pair(2, "Another Two"));
myMultiMap.insert(std::make_pair(3, "Three"));
// 查找键为 2 的所有元素
auto range = myMultiMap.equal_range(2);
for (auto it = range.first; it != range.second; ++it) {
std::cout << "找到键 2,值为: " << it->second << std::endl;
}
return 0;
}
总结:
key-value
对,使用 std::map
。std::multimap
。