目录
🤔map模板介绍:
🤔特点:
🤔map容器与哈希表:
🤔map的成员函数:
🙂map构造函数:
代码示例:
运行结果:
🙂map赋值函数:
代码示例:
运行结果:
🙂 map判断函数:
代码示例:
运行结果:
🙂 map的删除和插入:
代码示例
运行结果:
🙂 map的查找函数:
代码示例:
运行结果:
🙂 map自定义排序:
代码示例:
🤔multimap:
🙂特点:
代码示例:
运行结果:
🙂multimap与map的区别:
🤔结束!
🤔map模板介绍:
📖map是C++中的关联容器之一,它提供了一种将键与值相关联的方式。它的实现基于红黑树,具有自动排序和快速查找的特性。其中,键是唯一的,相同的键只能存在一个,而值则可以重复。map的基本操作包括插入、删除、查找等,还支持迭代器遍历和基于范围的操作。可以使用中括号运算符或者迭代器来访问map中的元素,也可以使用find函数查找指定键对应的值。由于map是基于红黑树实现的,因此其插入和查找的时间复杂度均为O(logN)。
🤔特点:
📖1. Map容器是C++ STL库中的重要容器之一,它可以快速查找和访问键值对。
📖2. 和其他STL容器一样,Map容器可以存储多种数据类型,包括内置数据类型和自定义类型。
📖3. Map容器的底层实现是一个红黑树,这使得它的插入与查找速度都很快,且仅需O(log n)的时间复杂度。
📖4. Map容器中的元素按照键进行排序,默认是按照键的升序进行排序。也可以通过自定义排序规则来进行降序排序。
📖5. Map容器的迭代器支持正向迭代和反向迭代。
📖6. Map容器有许多与迭代器相关的函数,如begin()、end()、rbegin()、rend()等,可以很方便地对容器进行遍历和操作。
📖7. Map容器还有许多成员函数,如size()、empty()、find()、insert()、erase()等等,以方便对容器进行封装和使用。
📖8. 使用Map容器时需要注意,由于红黑树是动态平衡的,因此它的插入、删除等操作会带来一定的时间复杂度,需要根据具体需求进行权衡和选择。
🤔map容器与哈希表:
Map和哈希表的相同之处在于它们都是用来存储键值对的容器,都可以快速查找和访问元素。具体来说,它们的相同点包括:
📖1. 都是关联式容器,元素之间的存储关系都是基于键的。
📖2. 都可以存储键值对,且可以任意添加、删除、修改元素。
📖3. 都可以快速查找元素,时间复杂度为O(1)或者O(logn)。
📖4. 都可以使用迭代器进行遍历,并且支持对元素的访问和修改。
📖5. 都可以存储自定义类型的数据,并可以自定义比较函数。
📖但是哈希表和Map容器不是同一个东西,它们是两种不同的容器类型。
📖Map容器是STL库中的一个关联式容器,内部使用红黑树来存储和管理元素,通过键值来快速查找元素,键值对是按照键进行排序的。
📖哈希表是一种基于哈希函数实现的数据结构,通过将元素的关键字映射到桶中来进行元素的存储和访问,具有快速插入、查找和删除的优势。
虽然在使用中可以通过哈希表来实现Map容器,但它们本质上是不同的数据结构。事实上,在一些特定的场合下,哈希表比Map容器效率更高,例如需要在海量数据中查找键值对。但是由于哈希表的实现需要使用哈希函数,因此它的编写和调试会更加困难一些,而Map容器的实现则更加简洁易懂。在选择使用容器时需要根据具体的需求来做出选择。
🤔map的成员函数:
🙂map构造函数:
📖1.默认构造函数:map<T1,T2> mp;
map<int, int> d1;
📖2.拷贝构造函数:map(const map & mp);
map<int, int> d2(d1);
代码示例:
#include<iostream>
#include<map>
using namespace std;
void printa(const map<int,int>& d)
{
for (auto it = d.begin(); it != d.end(); it++)
{
cout <<"键值为:" << it->first << " ";
cout <<"key值为:" <<it->second ;
cout << endl;
}
}
void test01()
{ //默认函数构造
map<int, int> d1;
d1.insert(pair<int, int>(2, 32));
d1.insert(pair<int, int>(5, 62));
d1.insert(pair<int, int>(3, 22));
d1.insert(pair<int, int>(7, 72));
d1.insert(pair<int, int>(6, 882));
d1.insert(pair<int, int>(4, 38));
cout << "默认函数构造结果为:"<<endl;
printa(d1);
//拷贝函数构造:
map<int, int> d2(d1);
cout << "拷贝函数构造结果为:" << endl;
printa(d2);
}
int main()
{
test01();
}
运行结果:
🙂map赋值函数:
📖1.重载等号运算符:map & operator=(const map &map);
map<int, int> d3;
d3 = d1;
代码示例:
#include<iostream>
#include<map>
using namespace std;
void printa(const map<int,int>& d)
{
for (auto it = d.begin(); it != d.end(); it++)
{
cout <<"键值为:" << it->first << " ";
cout <<"key值为:" <<it->second ;
cout << endl;
}
}
void test01()
{ //默认函数构造
map<int, int> d1;
d1.insert(pair<int, int>(2, 32));
d1.insert(pair<int, int>(5, 62));
d1.insert(pair<int, int>(3, 22));
d1.insert(pair<int, int>(7, 72));
d1.insert(pair<int, int>(6, 882));
d1.insert(pair<int, int>(4, 38));
cout << "默认函数构造结果为:"<<endl;
printa(d1);
//重载等号运算符:
map<int, int> d3;
d3 = d1;
cout << "重载等号运算符的结果为:" << endl;
printa(d3);
}
int main()
{
test01();
}
运行结果:
🙂 map判断函数:
📖1.返回容器中的元素个数:size();
📖2.判断容器是否为空:empty();
📖3.交换两个集合容器:swap();
代码示例:
#include<iostream>
using namespace std;
#include<map>
void printa(const map<int,int>& d)
{
for (auto it = d.begin(); it != d.end(); it++)
{
cout <<"键值为:" << it->first << " ";
cout <<"key值为:" <<it->second ;
cout << endl;
}
}
void test01()
{ //默认函数构造
map<int, int> d1;
d1.insert(pair<int, int>(2, 32));
d1.insert(pair<int, int>(5, 62));
d1.insert(pair<int, int>(3, 22));
d1.insert(pair<int, int>(7, 72));
d1.insert(pair<int, int>(6, 882));
d1.insert(pair<int, int>(4, 38));
cout << "默认函数构造结果为:"<<endl;
printa(d1);
cout << "d1容器是否为空(0为非空,1为空)" << d1.empty()<<endl;
cout << "d1容器的元素个数为" << d1.size()<<endl;
map<int, int> d2;
d2.swap(d1);
cout << "d2与d1交换结果后d2为:" << endl;
printa(d2);
}
int main()
{
test01();
}
运行结果:
🙂 map的删除和插入:
📖 1.在容器中插入元素:insert(elem);
📖 2.清除所有元素:clear();
📖 3.删除pos迭代器所指向的元素,返回下一个元素的迭代器: erase(pos);
📖 4.删除区间[beg, end)的所有元素,返回下一个元素的迭代器: erase(begin, end);
📖 5.删除容器中值为key的元素:erase(key);
代码示例
#include<iostream>
using namespace std;
#include<map>
void printa(const map<int,int>& d)
{
for (auto it = d.begin(); it != d.end(); it++)
{
cout <<"键值为:" << it->first << " ";
cout <<"key值为:" <<it->second ;
cout << endl;
}
}
void test01()
{ //默认函数构造
map<int, int> d1;
//插入的四种形式:
//第一种:
d1.insert(pair<int, int>(1, 10));
//第二种:
d1.insert(make_pair(2, 20));
//第三种:
d1.insert(map<int, int>::value_type(3, 30));
//第四种:
d1[4] = 40;
cout << "默认函数构造结果为:"<<endl;
printa(d1);
d1.erase(d1.begin());
cout << "删除了头部元素后结果为:" << endl;;
printa(d1);
d1.erase(5);
cout << "删除key值为5的元素后结果为:" << endl;
printa(d1);
d1.erase(d1.begin(), d1.end());
cout << "删除[beg,end)后结果为:" << endl;
printa(d1);
d1.insert(pair<int, int>(2, 32));
d1.insert(pair<int, int>(5, 62));
d1.insert(pair<int, int>(3, 22));
d1.insert(pair<int, int>(4, 92));
d1.insert(pair<int, int>(7, 82));
cout << "重新插入后结果为" << endl;
printa(d1);
d1.clear();
cout << "使用clear后结果为:";
printa(d1);
}
int main()
{
test01();
}
运行结果:
🙂 map的查找函数:
📖1.查找key是否存在,如果存在,返回该元素的迭代器,如果不存在,返回end():find();
📖2.统计key的元素个数:count(key);
*由于map不允许重复的key值出现,因此查找一个key的个数不是0(不存在)就是1(存在);
代码示例:
#include<iostream>
using namespace std;
#include<map>
void printa(const map<int,int>& d)
{
for (auto it = d.begin(); it != d.end(); it++)
{
cout <<"键值为:" << it->first << " ";
cout <<"key值为:" <<it->second ;
cout << endl;
}
}
void test01()
{ //默认函数构造
map<int, int> d1;
d1.insert(pair<int, int>(2, 32));
d1.insert(pair<int, int>(5, 62));
d1.insert(pair<int, int>(3, 22));
d1.insert(pair<int, int>(7, 72));
cout << "默认函数构造结果为:"<<endl;
printa(d1);
cout << "查找的键值为:" << d1.find(5)->first << "查找的key为:" << d1.find(5)->second << endl;
cout << "查找的键值有:" << d1.count(5)<<"个"<< endl;
}
int main()
{
test01();
}
运行结果:
🙂 map自定义排序:
📖关键点:自己重写仿函数,定义排序规则。
代码示例:
#include<iostream>
using namespace std;
#include<map>
class d
{
public:
bool operator()(int v1, int v2)const
{
return v1 > v2;
}
};
void printa(const map<int,int,d>& d)
{
for (auto it = d.begin(); it != d.end(); it++)
{
cout <<"键值为:" << it->first << " ";
cout <<"key值为:" <<it->second ;
cout << endl;
}
}
void test01()
{ //默认函数构造
map<int, int,d> d1;
d1.insert(pair<int, int>(2, 32));
d1.insert(pair<int, int>(5, 62));
d1.insert(pair<int, int>(3, 22));
d1.insert(pair<int, int>(7, 72));
cout << "默认函数构造结果为:"<<endl;
printa(d1);
}
int main()
{
test01();
}
运行结果:
📖通过仿函数实现自定义排序,我们使得键值的排序规则变为了由大到小。
🤔multimap:
📖multimap是C++ STL库中的一个关联式容器,用于存储键-值对,允许一个键对应多个值(即一个键可以在容器中有多个值)。与map容器不同的是,multimap允许一个键对应多个值,而map只允许一个键对应一个值。
📖multimap的内部实现基于红黑树,以键值来快速查找容器中的元素,元素按照键由小到大进行排序。
📖multimap与map容器相似,提供了一些成员函数来方便地访问和操作容器中的元素,如insert()、erase()、find()等函数。此外,multimap还支持同时使用多个键来查找元素,并支持按范围查找元素。
📖multimap容器适合存储一个键对应多个值的情况,例如在实现简单数据库的时候,可以使用multimap来存储数据库中的键值对,键可以是列名,值可以是该列下的所有值。
🙂特点:
multimap容器的特点如下:
📖1. 一个键可以对应多个值,即允许重复的key和value。
📖2. 它是一个关联式容器,内部使用红黑树实现,保证了元素的快速查找和排序。
📖3. 提供了一系列方法来访问和操作元素,如insert()、erase()、find()等函数。
📖4. 可以按范围查找元素,支持同时使用多个键查找元素。
📖5. 与其他容器相比,multimap容器内部的复杂度与元素个数和键值对数量无关,而与树高相关,保证了处理大量元素时的高效性。
📖6. 不支持使用[]访问元素。
multimap的主要优点在于,可以方便地存储一对多的键值对关系,且内部使用的红黑树可以实现元素的快速查找和按键排序。然而,由于支持重复的key和value,可能会导致一些插入和查找操作变得复杂,因此在使用时需要注意。
代码示例:
#include<iostream>
using namespace std;
#include<map>
class d
{
public:
bool operator()(int v1, int v2)const
{
return v1 > v2;
}
};
void printa(const multimap<int,int,d>& d)
{
for (auto it = d.begin(); it != d.end(); it++)
{
cout <<"键值为:" << it->first << " ";
cout <<"key值为:" <<it->second;
cout << endl;
}
}
void test01()
{ //默认函数构造
multimap<int, int,d> d1;
d1.insert(pair<int, int>(2, 32));
d1.insert(pair<int, int>(5, 62));
d1.insert(pair<int, int>(3, 22));
d1.insert(pair<int, int>(3, 23));
d1.insert(pair<int, int>(7, 72));
cout << "默认函数构造结果为:"<<endl;
printa(d1);
}
int main()
{
test01();
}
运行结果:
由此我们可以看出multimap可以存储键值相同的元素。
🙂multimap与map的区别:
multimap和map本质上都是关联式容器,以键值对存储元素,且键值不能重复,但在插入元素时有些许不同:
📖map容器要求元素的键值必须唯一,若元素已经存在,则插入失败。
📖multimap容器允许元素的键值重复,可以插入多个具有相同键值的元素。
在使用迭代器访问容器元素时,它们也稍有不同:
📖在map容器中,每个元素都是一个键值对,通过迭代器访问时,迭代器的指针所指向的是一个pair类型的变量,该变量包含两个成员变量:first表示键,second表示值。
📖在multimap容器中,每个元素也是一个键值对,但是可以包含重复的键值,通过迭代器访问时,迭代器的指针所指向的是一个pair类型的指针或引用,这是因为对于一个键值来说,可能存在多个值。
此外,由于multimap容器允许元素键值重复,因此在删除元素时需要注意,由于删除操作只会删除一个键值对,因此如果要删除多个键值相同的元素,需要结合find()函数一起使用来实现。而对于map容器而言,由于元素键值唯一,可以通过关键字直接删除元素,操作比较简单。