C++ map类成员介绍 (map与multimap)

news/2024/11/29 2:37:55/

目录

🤔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容器而言,由于元素键值唯一,可以通过关键字直接删除元素,操作比较简单

🤔结束!


http://www.ppmy.cn/news/109703.html

相关文章

陕西省养老服务人才培训基地申报条件范围、认定材料流程

今天为大家整理了陕西省养老服务人才培训基地申报条件范围、奖励措施等内容&#xff0c;感兴趣的朋友们可以了解一下&#xff01; 如果想要申报西安市、宝鸡市、铜川市、咸阳市、渭南市、延安市、汉中市、榆林市、安康市、商洛市的项目政策&#xff0c;详情见下图 目标任务 陕…

spdk记录

spdk记录 hello_bdev命令行参数 往期文章&#xff1a; spdk环境搭建 hello_bdev 代码路径&#xff1a;examples/bdev/hello_world/hello_bdev.c 可执行文件路径&#xff1a;build/examples/hello_bdev 刚开始直接执行hello_bdev显示找不到Malloc0 ./build/examples/hello_b…

C++ vector模板和deque的简单应用

目录 &#x1f914;vector模板和deque的简单介绍: &#x1f914;vector和deque的主要不同之处&#xff1a; &#x1f914;今天我们用vector模板和deque模板实现以下简单的功能&#xff1a; 代码实现&#xff1a; &#x1f914;讲解&#xff1a; &#x1f914;vector模板和d…

代码随想录算法训练营第三十七天|738.单调递增的数字 968.监控二叉树

目录 LeeCode 738.单调递增的数字 LeeCode 968.监控二叉树 LeeCode 738.单调递增的数字 738. 单调递增的数字 - 力扣&#xff08;LeetCode&#xff09; 思路&#xff1a;从后向前遍历&#xff0c;遇到strNum[i - 1] > strNum[i]的情况&#xff0c;则strNum[i - 1]--&…

代码随想录算法训练营第四十一天|343. 整数拆分 96.不同的二叉搜索树

目录 LeeCode 343. 整数拆分 动态规划法 贪心解法 LeeCode 96.不同的二叉搜索树 LeeCode 343. 整数拆分 343. 整数拆分 - 力扣&#xff08;LeetCode&#xff09; 动态规划法 思路&#xff1a; 1.确定dp数组及下标含义&#xff1a;dp[i]&#xff1a;分拆数字i&#xff0…

git使用X篇_1_SVN和GIT的版本控制区别及git等的使用方法

GIT是分布式版本控制系统&#xff0c;可以在本地记录代码的修改过程而不一定上传至SVN服务端&#xff1a; 详细使用差异见博客&#xff1a; 版本控制&#xff1a;SVN和GIT的一些使用感受 版本控制&#xff1a;SVN和GIT的一些使用感受&#xff08;续&#xff09; git/svn_SVN和G…

Centos6.5环境Nginx 1.16.1升级到1.24.0版本

一、背景 2023年4月11日&#xff0c;官方发布了Nginx最新稳定版&#xff0c;版本号为 1.24.0。该版本是基于1.23.x&#xff08;1.23.0 - 1.23.4&#xff09;开发版的Bug修复&#xff0c;以及一些新特性的加入&#xff0c;而形成的稳定版。安全部门扫描后&#xff0c;发现现场不…

二分查找三道题

二分查找 两种写法&#xff1a;左闭右闭[left,right]、左闭右开[left,right) 主要有几点不同&#xff1a;1. right是从num.length开始还是从num.length-1开始。2.left<还是<right。3.rightmid还是mid1 左闭右闭写法&#xff1a; public int search(int[] nums, int targ…