【STL源码剖析】第五章 关联式容器 之 set、map、multiset和multimap

2024-08-22 13:08

本文主要是介绍【STL源码剖析】第五章 关联式容器 之 set、map、multiset和multimap,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

set

  1. 所有的元素都会根据元素的键值自动被排序。set的元素不像map那样可以同时拥有实值(value)和键值(key),set元素的键值就是实值。set不允许两个元素有相同的键值。

  2. 不可以通过set的迭代器改变set的元素值。因为set元素值就是其键值,关系到set元素的排列规则。如果任意改变set元素值,会严重破坏set组织。set源码中,set<T>::iterator被定义为底层RB-tree的const_iterator,杜绝写入操作。换句话,set iterators是一种constant iterators。

  3. set拥有与list相同的某些性质:当客户端对它进行元素新增操作(insert)或删除操作(erase)时,操作之前的所有迭代器,在操作完成之后依然有效。当然,被删除的那个元素的迭代器必然是个例外。

  4. STL set以RB-tree为底层机制,set的操作几乎都是转调用RB-tree的函数而已。

set测试代码:

  #include<set>#include<iostream>using namespace std;int main(){    int ia[] = { 5, 3, 4, 1, 6, 2 };    set<int> iset(begin(ia), end(ia));    cout << "size=" << iset.size() << endl; //size=6    cout << "3 count=" << iset.count(3) << endl;//3 count=1    iset.insert(3);    cout << "size=" << iset.size() << endl;//size=6    cout << "3 count=" << iset.count(3) << endl;//3 count=1    iset.insert(7);    cout << "size=" << iset.size() << endl;//size=7    cout << "3 count=" << iset.count(3) << endl;//3 count=1    iset.erase(1);    cout << "size=" << iset.size() << endl;//size=6    cout << "1 count=" << iset.count(1) << endl;//1 count=0    set<int>::iterator it;    for (it = iset.begin(); it != iset.end(); ++it)        cout << *it << " "; //2 3 4 5 6 7    cout << endl;    it = find(iset.begin(), iset.end(), 3);    if (it != iset.end())        cout << "3 found" << endl;//3 found    it = find(iset.begin(), iset.end(), 1);    if (it == iset.end())        cout << "1 not found" << endl;//1 not found    system("pause");    return 0;}

map

  1. map的特性是,所有元素都会根据元素的键值自动被排序。map的所有元素都是pair,同时拥有实值(value)和键值(key)。pair的第一元素被视为键值,第二元素被视为实值。map不允许两个元素拥有相同的键值。下面是<stl_pair.h>中pair定义:

      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) {}}

  2. 不能通过map的迭代器改变map的键值,但通过map的迭代器能改变map的实值。因此map的iterators既不是一种const iterators,也不是一种mutable iterators。

  3. map拥有和list相同的某些性质:当客户端对它进行元素新增操作(insert)或删除操作(erase)时,操作之前的所有迭代器,在操作完成之后都依然有效。当然,被删除的那个元素的迭代器必然是个例外。

  4. 由于RB-tree是一种平衡二叉搜索树,自动排序的效果很不错,所以标准的STL map即以RB-tree为底层机制。又由于map所开放的各种操作接口,RB-tree也都提供了,所以几乎所有的map操作行为,都只是转调用RB-tree的操作行为而已。

  #include<map>#include<iostream>#include<string>using namespace std;int main(){    map<string, int> simap;            //以string为键值,以int为实值    simap[string("jjhou")] = 1;        //第一对内容是("jjhou",1)    simap[string("jerry")] = 2;        //第一对内容是("jerry",2)    simap[string("jason")] = 3;        //第一对内容是("jason",3)    simap[string("jimmy")] = 4;        //第一对内容是("jimmy",4)    pair<string, int> value(string("david"), 5);    simap.insert(value);    map<string, int>::iterator simap_iter = simap.begin();    for (; simap_iter != simap.end(); ++simap_iter)        cout << simap_iter->first << ' ' << simap_iter->second << endl;                                                                //david 5   //按键值排序                                                                //jason 3                                                                //jerry 2                                                                //jimmy 4                                                                //jjhou 1    int number = simap[string("jjhou")];    cout << number << endl;                                     //1    map<string, int>::iterator ite1;    //面对关联式容器,应使用其所提供的find函数来搜寻元素,会比STL算法find()更有效率。因为STL find()只是循序搜索    ite1 = simap.find(string("mchen"));    if (ite1 == simap.end())        cout << "mchen not found" << endl;                      //mchen not found    ite1 = simap.find(string("jerry"));    if (ite1 != simap.end())        cout << "jerry found" << endl;                         //jerry found    ite1->second = 9;    int number2 = simap[string("jerry")];    cout << number2 << endl;                                   //9}

multiset

multiset的特性以及用法和set完全相同,唯一的差别在于它允许键值重复,因此它的插入操作采用的是底层机制RB-tree的insert_equal()而非insert_unique()。

  #include<set>#include<iostream>#include<vector>using namespace std;int main() {    vector<int> a = { 5, 3, 4, 1, 6, 2 };    multiset<int> iset(a.begin(),a.end());    cout << "size=" << iset.size() << endl; //size=6    cout << "3 count=" << iset.count(3) << endl;//3 count=1    iset.insert(3); //和set区别的地方    cout << "size=" << iset.size() << endl;//size=7    cout << "3 count=" << iset.count(3) << endl;//3 count=2    iset.insert(7);    cout << "size=" << iset.size() << endl;//size=8    cout << "3 count=" << iset.count(3) << endl;//3 count=2    iset.erase(1);    cout << "size=" << iset.size() << endl;//size=7    cout << "1 count=" << iset.count(1) << endl;//1 count=0    set<int>::iterator it;    for (it = iset.begin(); it != iset.end(); ++it)        cout << *it << " "; //2 3 3 4 5 6 7    cout << endl;    it = find(iset.begin(), iset.end(), 3);    if (it != iset.end())        cout << "3 found" << endl;//3 found    it = find(iset.begin(), iset.end(), 1);    if (it == iset.end())        cout << "1 not found" << endl;//1 not found    system("pause");    return 0;}

multimap

multimap的特性以及用法与map完全相同,唯一的差别在于它允许键值重复,因此它的插入操作采用的是底层机制RB-tree的insert_equal()而非insert_unique()。

  #include<map>#include<string>#include<iostream>using namespace std;int main(){    multimap<string, int> mp;//multimap没有下标操作    mp.insert(pair<string, int>("Jack", 1));    mp.insert(pair<string, int>("John", 2));    mp.insert(pair<string, int>("Lily", 3));    mp.insert(pair<string, int>("Kate", 4));//按键值字典序排序    mp.insert(pair<string, int>("Tom", 5));              //Jack 1    mp.insert(pair<string, int>("John", 8));            //John 2                                                           //John 8       map<string, int>::iterator it;                      //Kate 4    for (it = mp.begin(); it != mp.end(); ++it)         //Lily 3        cout << it->first << " " << it->second << endl; //Tom 5    it = mp.find("John");    if (it != mp.end())        cout << "John found" << endl; //John found    it->second = 8;    it = mp.find("John");    cout << it->second << endl;//8    system("pause");    return 0;}

这篇关于【STL源码剖析】第五章 关联式容器 之 set、map、multiset和multimap的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1096361

相关文章

Java中Map.Entry()含义及方法使用代码

《Java中Map.Entry()含义及方法使用代码》:本文主要介绍Java中Map.Entry()含义及方法使用的相关资料,Map.Entry是Java中Map的静态内部接口,用于表示键值对,其... 目录前言 Map.Entry作用核心方法常见使用场景1. 遍历 Map 的所有键值对2. 直接修改 Ma

Java Multimap实现类与操作的具体示例

《JavaMultimap实现类与操作的具体示例》Multimap出现在Google的Guava库中,它为Java提供了更加灵活的集合操作,:本文主要介绍JavaMultimap实现类与操作的... 目录一、Multimap 概述Multimap 主要特点:二、Multimap 实现类1. ListMult

Java中JSON格式反序列化为Map且保证存取顺序一致的问题

《Java中JSON格式反序列化为Map且保证存取顺序一致的问题》:本文主要介绍Java中JSON格式反序列化为Map且保证存取顺序一致的问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未... 目录背景问题解决方法总结背景做项目涉及两个微服务之间传数据时,需要提供方将Map类型的数据序列化为co

8种快速易用的Python Matplotlib数据可视化方法汇总(附源码)

《8种快速易用的PythonMatplotlib数据可视化方法汇总(附源码)》你是否曾经面对一堆复杂的数据,却不知道如何让它们变得直观易懂?别慌,Python的Matplotlib库是你数据可视化的... 目录引言1. 折线图(Line Plot)——趋势分析2. 柱状图(Bar Chart)——对比分析3

SpringIOC容器Bean初始化和销毁回调方式

《SpringIOC容器Bean初始化和销毁回调方式》:本文主要介绍SpringIOC容器Bean初始化和销毁回调方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录前言1.@Bean指定初始化和销毁方法2.实现接口3.使用jsR250总结前言Spring Bea

Java使用Stream流的Lambda语法进行List转Map的操作方式

《Java使用Stream流的Lambda语法进行List转Map的操作方式》:本文主要介绍Java使用Stream流的Lambda语法进行List转Map的操作方式,具有很好的参考价值,希望对大... 目录背景Stream流的Lambda语法应用实例1、定义要操作的UserDto2、ListChina编程转成M

MySQL复合查询从基础到多表关联与高级技巧全解析

《MySQL复合查询从基础到多表关联与高级技巧全解析》本文主要讲解了在MySQL中的复合查询,下面是关于本文章所需要数据的建表语句,感兴趣的朋友跟随小编一起看看吧... 目录前言:1.基本查询回顾:1.1.查询工资高于500或岗位为MANAGER的雇员,同时还要满足他们的姓名首字母为大写的J1.2.按照部门

Android实现一键录屏功能(附源码)

《Android实现一键录屏功能(附源码)》在Android5.0及以上版本,系统提供了MediaProjectionAPI,允许应用在用户授权下录制屏幕内容并输出到视频文件,所以本文将基于此实现一个... 目录一、项目介绍二、相关技术与原理三、系统权限与用户授权四、项目架构与流程五、环境配置与依赖六、完整

Android实现定时任务的几种方式汇总(附源码)

《Android实现定时任务的几种方式汇总(附源码)》在Android应用中,定时任务(ScheduledTask)的需求几乎无处不在:从定时刷新数据、定时备份、定时推送通知,到夜间静默下载、循环执行... 目录一、项目介绍1. 背景与意义二、相关基础知识与系统约束三、方案一:Handler.postDel

Java 正则表达式URL 匹配与源码全解析

《Java正则表达式URL匹配与源码全解析》在Web应用开发中,我们经常需要对URL进行格式验证,今天我们结合Java的Pattern和Matcher类,深入理解正则表达式在实际应用中... 目录1.正则表达式分解:2. 添加域名匹配 (2)3. 添加路径和查询参数匹配 (3) 4. 最终优化版本5.设计思