【1】map容器

map 是关联容器。容器中的每一个元素都是由一个键值和一个数据值组成的。

set 是一个集合它以其元素作为键值(同一个键值只能出现一次),且默认以升序排列。

list 是一个顺序容器。

【2】map容器使用方法以及实例

(1)定义、插入数据方法实例

 // map容器定义、插入数据方式代码
#include<map>
#include<string>
#include<iostream>
using namespace std; // 打印map容器数据
void print(map<int, string>& mapStu, int nValue)
{
cout << "mapStu" << nValue << "数据信息:" << endl;
cout << "size: " << mapStu.size() << endl;
map<int, string>::iterator iter = mapStu.begin();
for (; iter != mapStu.end(); ++iter)
{
cout << "key: " << iter->first << " value: " << iter->second << endl;
}
cout << endl;
} void main()
{
// 第一种定义map的方法
map<int, string> mapStu1;
// 第二种定义map的方法
typedef map<int, string> mapType;
mapType mapStu2, mapStu3, mapStu4; // 第一种插入数据方法:用insert函数插入value_type数据
mapStu1.insert(map<int, string>::value_type(, "Qin"));
mapStu1.insert(map<int, string>::value_type(, "Sun"));
mapStu1.insert(map<int, string>::value_type(, "Wang"));
mapStu1.insert(map<int, string>::value_type(, "Zhao"));
print(mapStu1, );
// 第二种插入数据方法:用insert函数插入pair数据
mapStu2.insert(pair<int, string>(, "Qin"));
mapStu2.insert(pair<int, string>(, "Sun"));
mapStu2.insert(pair<int, string>(, "Wang"));
mapStu2.insert(pair<int, string>(, "Zhao"));
print(mapStu2, );
// 第三种插入数据方法:用insert函数插入make_pair数据
mapStu3.insert(make_pair<int, string>(, "Qin"));
mapStu3.insert(make_pair<int, string>(, "Sun"));
mapStu3.insert(make_pair<int, string>(, "Wang"));
mapStu3.insert(make_pair<int, string>(, "Zhao"));
print(mapStu3, );
// 第四种插入数据方法:数组插入法
mapStu4[] = "Qin";
mapStu4[] = "Sun";
mapStu4[] = "Wang";
mapStu4[] = "Zhao";
print(mapStu4, ); pair<map<int, string>::iterator, bool> iter_pair;
iter_pair = mapStu1.insert(map<int, string>::value_type(, "Li"));
cout << "插入成功与否:" << iter_pair.second << endl; system("pause");
} // run out
/*
mapStu1数据信息:
size: 3
key: 1 value: Qin
key: 2 value: Sun
key: 3 value: Wang mapStu2数据信息:
size: 3
key: 1 value: Qin
key: 2 value: Sun
key: 3 value: Wang mapStu3数据信息:
size: 3
key: 1 value: Qin
key: 2 value: Sun
key: 3 value: Wang mapStu4数据信息:
size: 3
key: 1 value: Qin
key: 2 value: Zhao
key: 3 value: Wang 插入成功与否:0
请按任意键继续. . .
*/

分析总结:

以上四种用法,虽然都可以实现数据的插入,但是它们是有区别的。

当然,第一、二、三种在效果上是完全一样的,用insert函数插入数据,在数据的插入过程中涉及到集合的唯一性这个概念:

即当map中有这个关键字时,insert操作再插入数据是不会成功的。

但是,用数组(第四种)方式就不同了,它可以覆盖以前该关键字对应的值,用程序说明如下:

mapStu1.insert(map<int, string>::value_type(2, "Sun"));

mapStu1.insert(map<int, string>::value_type(2, "Zhao"));

上面这两条语句执行后,mapStu1中2这个关键字对应的值是“Sun”,第二条语句并没有生效。

那么,这就涉及到我们怎么知道insert语句是否插入成功的问题?可以用pair来获得是否插入成功,程序如下:

pair<map<int, string>::iterator, bool> iter_pair;

iter_pair = mapStu1.insert(map<int, string>::value_type(3, "Li"));

我们通过pair的第二个变量来判断是否插入成功,它的第一个变量返回的是一个map的迭代器,

如果插入成功的话迭代器的变量iter_pair.second应该是true,否则为false。

(2)遍历map容器的三种方式

程序代码如下:

 #include <map>
#include <iostream>
#include <string>
using namespace std; // 第一种方式
void print1(map<int, string>& mapStu)
{
cout << "第一种遍历方式:" << endl;
cout << "size: " << mapStu.size() << endl;
// 迭代map容器中的数据
map<int, string>::iterator iter = mapStu.begin();
for (; iter != mapStu.end(); ++iter)
{
cout << "key: " << iter->first << " value: " << iter->second << endl;
}
cout << endl;
} // 第二种方式
void print2(map<int, string>& mapStu)
{
cout << "第二种遍历方式:" << endl;
cout << "size: " << mapStu.size() << endl;
// 迭代map容器中的数据
map<int, string>::reverse_iterator iter = mapStu.rbegin();
for (; iter != mapStu.rend(); ++iter)
{
cout << "key: " << iter->first << " value: " << iter->second << endl;
} cout << endl;
} // 第三种方式
void print3(map<int, string>& mapStu)
{
cout << "第三种遍历方式:" << endl;
int nSize = mapStu.size();
cout << "size: " << mapStu.size() << endl;
// 迭代map容器中的数据
for(int nIndex = ; nIndex < nSize + ; ++nIndex)
{
cout << "<" << nIndex << " :: " << mapStu[nIndex] << ">" << endl;
}
} void main()
{
typedef map<int, string> mapType;
mapType mapStu; // 用insert函数插入value_type数据
mapStu.insert(map<int, string>::value_type(, "Qin"));
mapStu.insert(map<int, string>::value_type(, "Sun"));
mapStu.insert(map<int, string>::value_type(, "Wang"));
mapStu.insert(map<int, string>::value_type(, "Zhao"));
print1(mapStu); // 第一种方式
print2(mapStu); // 第二种方式
print3(mapStu); // 第三种方式 system("pause");
}
// run out:
/*
第一种遍历方式:
size: 4
key: 1 value: Qin
key: 2 value: Sun
key: 3 value: Wang
key: 4 value: Zhao 第二种遍历方式:
size: 4
key: 4 value: Zhao
key: 3 value: Wang
key: 2 value: Sun
key: 1 value: Qin 第三种遍历方式:
size: 4
<1 :: Qin>
<2 :: Sun>
<3 :: Wang>
<4 :: Zhao>
请按任意键继续. . .
*/

(3)查找数据的三种方式

应用实例代码如下:

 // 三种查找数据的方式
#include <map>
#include <iostream>
#include <string>
using namespace std; // 第一种方式
void print1(map<int, string>& mapStu)
{
cout << "遍历容器数据:" << endl;
cout << "size: " << mapStu.size() << endl;
// 迭代map容器中的数据
map<int, string>::iterator iter = mapStu.begin();
for (; iter != mapStu.end(); ++iter)
{
cout << "key: " << iter->first << " value: " << iter->second << endl;
}
} void main()
{
typedef map<int, string> mapType;
mapType mapStu; // 用insert函数插入value_type数据
mapStu.insert(map<int, string>::value_type(, "Qin"));
mapStu.insert(map<int, string>::value_type(, "Sun"));
mapStu.insert(map<int, string>::value_type(, "Wang"));
mapStu.insert(map<int, string>::value_type(, "Zhao"));
// 第一种查找数据方式
// count函数求的是关键字key的个数?key是不能重复的,所以返回只有0和1两种结果。
cout << "查找关键字3的结果 : " << mapStu.count() << endl;
cout << "查找关键字5的结果: " << mapStu.count() << endl;
// 第二种查找数据方式
map<int, string>::iterator iter;
iter = mapStu.find();
if (iter != mapStu.end())
{
cout << "Find, the value is " << iter->second << endl;
}
else
{
cout << "Do not Find !" << endl;
}
// 第三种查找数据方式
print1(mapStu);
iter = mapStu.lower_bound();
{
cout << "lower_bound(2) :: (不小于2) " << iter->second << endl;
} iter = mapStu.lower_bound();
{
cout << "lower_bound(3) :: (不小于3) " << iter->second << endl;
} iter = mapStu.upper_bound();
{
cout << "upper_bound(2) :: (大于2) " << iter->second << endl;
} iter = mapStu.upper_bound();
{
cout << "upper_bound(3) :: (大于3) " << iter->second << endl;
} pair<map<int, string>::iterator, map<int, string>::iterator> mapPair;
mapPair = mapStu.equal_range();
if (mapPair.first == mapPair.second)
{
cout << "equal_range(2) :: Do not Find!" << endl;
}
else
{
cout << "equal_range(2) :: Find!" << endl;
} mapPair = mapStu.equal_range();
if (mapPair.first == mapPair.second)
{
cout << "equal_range(5) :: Do not Find!" << endl;
}
else
{
cout << "equal_range(5) :: Find!" << endl;
} system("pause");
}
// run out:
/*
查找关键字3的结果 : 1
查找关键字5的结果: 0
Find, the value is Qin
遍历容器数据:
size: 4
key: 1 value: Qin
key: 2 value: Sun
key: 3 value: Wang
key: 4 value: Zhao
lower_bound(2) :: (不小于2) Sun
lower_bound(3) :: (不小于3) Wang
upper_bound(2) :: (大于2) Wang
upper_bound(3) :: (大于3) Zhao
equal_range(2) :: Find!
equal_range(5) :: Do not Find!
请按任意键继续. . .
*/

注意:

lower_bound(x)不是下界,而是大于等于x的最小值。

upper_bound(x) 大于x的最小值。

(4)查询、修改、删除、大小、比较、清空、判空等等方法。

应用实例代码如下:

 #include <map>
#include <string>
#include <iostream>
using namespace std; // 打印map容器数据
void print(map<int, string>& mapStu)
{
cout << "size: " << mapStu.size() << endl;
// 迭代map容器中的数据
map<int, string>::iterator iter = mapStu.begin();
for (; iter != mapStu.end(); ++iter)
{
cout << "key: " << iter->first << " value: " << iter->second << endl;
}
cout << endl;
} void main()
{
typedef map<int, string> mapType;
mapType mapStu1; // 用insert函数插入value_type数据
mapStu1.insert(map<int, string>::value_type(, "Qin"));
mapStu1.insert(map<int, string>::value_type(, "Sun"));
mapStu1.insert(map<int, string>::value_type(, "Wang"));
mapStu1.insert(map<int, string>::value_type(, "Zhao"));
print(mapStu1);
// 查找数据的两种方式:
// 方式1:
string str2 = mapStu1[];
cout << str2 << endl;
// 方式2:
mapType::iterator my_Iter;
my_Iter = mapStu1.find();
string str3 = my_Iter->second;
cout << str3 << endl << endl;
// 修改数据的两种方式:
// 方式1:
mapStu1[] = "Ma";
// 方式2:
my_Iter->second = "Yuan";
print(mapStu1);
// size 函数 和 empty函数
cout << "size() :: " << mapStu1.size() << endl;
cout << "empty() :: " << mapStu1.empty() << endl;
mapStu1.clear();
cout << "size() :: " << mapStu1.size() << endl;
cout << "empty() :: " << mapStu1.empty() << endl;
// 比较 ==、>=、<=、!=
mapType mapStu2;
cout << "mapStu1 == mapStu2 :: " << (mapStu1 == mapStu2) << endl;
cout << "mapStu1 >= mapStu2 :: " << (mapStu1 >= mapStu2) << endl;
cout << "mapStu1 <= mapStu2 :: " << (mapStu1 <= mapStu2) << endl;
cout << "mapStu1 != mapStu2 :: " << (mapStu1 != mapStu2) << endl << endl; mapStu1.insert(map<int, string>::value_type(, "Qin"));
mapStu1.insert(map<int, string>::value_type(, "Sun"));
mapStu1.insert(map<int, string>::value_type(, "Wang"));
mapStu1.insert(map<int, string>::value_type(, "Qiang"));
mapStu1.insert(map<int, string>::value_type(, "Huang"));
mapStu1.insert(map<int, string>::value_type(, "Li"));
mapStu1.insert(map<int, string>::value_type(, "Hou"));
mapStu1.insert(map<int, string>::value_type(, "Lin"));
mapStu1.insert(map<int, string>::value_type(, "Li")); // 删除操作
cout << "删除前打印数据信息:" << endl;
print(mapStu1);
mapType::iterator iter;
// 第一种删除(代码1)
for (iter = mapStu1.begin(); iter != mapStu1.end();)
{
if ( == iter->first)
{
iter = mapStu1.erase(iter);
}
else
{
++iter;
}
} // 第一种删除(代码2)(注意代码层面的差异)
for (iter = mapStu1.begin(); iter != mapStu1.end();)
{
if ("Li" == iter->second)
{
mapStu1.erase(iter++);
}
else
{
++iter;
}
}
cout << "删除关键字5 以及 值“Li”后: " << endl;
print(mapStu1); // 第一种删除(代码3)(注意代码层面的差异)
my_Iter = mapStu1.find();
mapStu1.erase(my_Iter);
cout << "删除关键字2后: " << endl;
print(mapStu1); // 第二种删除(直接删除关键字)
int nResult = mapStu1.erase(); // 如果删除了会返回1,否则返回0
cout << nResult << endl;
cout << "删除关键字3后: " << endl;
print(mapStu1); // 第三种删除(用迭代器,成片的删除)
mapStu1.erase(++mapStu1.begin(), mapStu1.end());
cout << "剩第一位,其它全部删除后: " << endl;
print(mapStu1); system("pause");
} // run out:
/*
size: 3
key: 1 value: Qin
key: 2 value: Sun
key: 3 value: Wang Sun
Wang size: 3
key: 1 value: Qin
key: 2 value: Ma
key: 3 value: Yuan size() :: 3
empty() :: 0
size() :: 0
empty() :: 1
mapStu1 == mapStu2 :: 1
mapStu1 >= mapStu2 :: 1
mapStu1 <= mapStu2 :: 1
mapStu1 != mapStu2 :: 0 删除前打印数据信息:
size: 9
key: 1 value: Qin
key: 2 value: Sun
key: 3 value: Wang
key: 4 value: Qiang
key: 5 value: Huang
key: 6 value: Li
key: 7 value: Hou
key: 8 value: Lin
key: 9 value: Li 删除关键字5 以及 值“Li”后:
size: 6
key: 1 value: Qin
key: 2 value: Sun
key: 3 value: Wang
key: 4 value: Qiang
key: 7 value: Hou
key: 8 value: Lin 删除关键字2后:
size: 5
key: 1 value: Qin
key: 3 value: Wang
key: 4 value: Qiang
key: 7 value: Hou
key: 8 value: Lin 1
删除关键字3后:
size: 4
key: 1 value: Qin
key: 4 value: Qiang
key: 7 value: Hou
key: 8 value: Lin 剩第一位,其它全部删除后:
size: 1
key: 1 value: Qin 请按任意键继续. . .
*/

(5)map 容器排序问题

请看下面一段代码:

 #include <map>
#include <cstring>
using namespace std; typedef struct tagStudentInfo
{
int nID;
string strName;
} StudentInfo, *PStudentInfo; // 学生信息 void main()
{
// 用学生信息映射分数
map<StudentInfo, int> mapStudent;
StudentInfo studentInfo;
studentInfo.nID = ;
studentInfo.strName = "student_one";
mapStudent.insert(pair<StudentInfo, int>(studentInfo, ));
studentInfo.nID = ;
studentInfo.strName = "student_two";
mapStudent.insert(pair<StudentInfo, int>(studentInfo, ));
}

注意:以上程序编译无法通过!

由编译器错误提示分析:排序问题!STL中默认是采用小于号来排序的,当关键字是一个结构体时,涉及到排序就会出现问题。

因为它没有小于号操作,insert等函数在编译的时候过不去,下面给出两个方法解决这个问题:

1、解决方法1,重载运算符。

 // 解决方法1

 #include <map>
#include <cstring>
using namespace std; typedef struct tagStudentInfo
{
int nID;
string strName; bool operator < (tagStudentInfo const & _A)const
{
// 这个函数指定排序策略,按nID排序,如果nID相等的话,按strName排序。
if (nID < _A.nID)
return true;
if (nID == _A.nID)
return strName.compare(_A.strName) < ; return false;
}
} StudentInfo, *PStudentInfo; // 学生信息 void main()
{
// 用学生信息映射分数
map<StudentInfo, int> mapStudent;
StudentInfo studentInfo;
studentInfo.nID = ;
studentInfo.strName = "student_one";
mapStudent.insert(pair<StudentInfo, int>(studentInfo, ));
studentInfo.nID = ;
studentInfo.strName = "student_two";
mapStudent.insert(pair<StudentInfo, int>(studentInfo, ));
}

2、解决方法2,仿函数。

 // 解决方法2

 #include <map>
#include <cstring>
using namespace std; typedef struct tagStudentInfo
{
int nID;
string strName;
} StudentInfo, *PStudentInfo; // 学生信息 class sort
{
public:
bool operator()(StudentInfo const & _A, StudentInfo const & _B) const
{
if (_A.nID < _B.nID)
return true;
if (_A.nID == _B.nID)
return _A.strName.compare(_B.strName) < ; return false;
}
}; void main()
{
// 用学生信息映射分数
map<StudentInfo, int, sort> mapStudent;
StudentInfo studentInfo;
studentInfo.nID = ;
studentInfo.strName = "student_one";
mapStudent.insert(pair<StudentInfo, int>(studentInfo, ));
studentInfo.nID = ;
studentInfo.strName = "student_two";
mapStudent.insert(pair<StudentInfo, int>(studentInfo, ));
}

(6)待续...

【3】总结说明

(1)由于STL是一个统一的整体,map的很多用法都和STL中其它的东西结合在一起。

比如,在排序方面,这里默认用的是小于号,即less<>,如果要从大到小排序呢,这里涉及到的东西很多,在此无法一一加以说明。

(2)map容器内部有序,由红黑树保证,因此很多函数执行的时间复杂度都是log2N的,用map函数可以实现的功能,而STL Algorithm也可以完成该功能。

但是,建议用map自带函数,效率更高一些。

(3)map在空间上的特性。

由于map的每个数据对应红黑树上的一个节点,这个节点在不保存你的数据时,是占用16个字节:

一个父节点指针,左右两个孩子指针,还有一个枚举值(标示红黑的,相当于平衡二叉树中的平衡因子)。

Good  Good  Study,  Day  Day  Up.

顺序  选择  循环  总结

STL容器之map的更多相关文章

  1. [知识点]C++中STL容器之map

    UPDATE(20190416):写完vector和set之后,发现不少内容全部引导到map上了……于是进行了一定的描述补充与更正. 零.STL目录 1.容器之map 2.容器之vector 3.容器 ...

  2. C++ STL容器之 map

    map 是一种有序无重复的关联容器. 关联容器与顺序容器不同,他们的元素是按照关键字来保存和访问的,而顺序元素是按照它们在容器中的位置保存和访问的. map保存的是一种 key - value 的pa ...

  3. [知识点]C++中STL容器之set

    零.STL目录 1.容器之map 2.容器之vector 3.容器之set 一.前言 继上期的vector之后,我们又迎来了另一个类数组的STL容器——set. 二.用途与特性 set,顾名思义,集合 ...

  4. [知识点]C++中STL容器之vector

    零.STL目录 1.容器之map 2.容器之vector 3.容器之set 一.前言 关于STL和STL容器的概念参见STL系列第一篇——map(见上).今天介绍第二个成员——vector. 二.用途 ...

  5. iBinary C++STL模板库关联容器之map/multimap

    目录 一丶关联容器map/multimap 容器 二丶代码例子 1.map的三种插入数据的方法 3.map集合的遍历 4.验证map集合数据是否插入成功 5.map数据的查找 6.Map集合删除元素以 ...

  6. STL关联式容器之map和multimap

    一,map和multimap的概念 1.map和multimap的基本知识 map是标准的关联式容器,一个map是一个键值对序列,即(key,value)对.它提供基于key的快速检索能力. map中 ...

  7. C++ 关联容器之map插入相同键元素与查找元素操作

    一.插入相同键元素操作 (1)insert方法 在map中的键必须是唯一的,当想map中连续插入键相同但值不同的元素时,编译和运行时都不会发生任何错误,系统会忽略后面的对已存在的键的插入操作,如 ma ...

  8. STL容器之vector

    [1]模板类vector 模板类vector可理解为广义数组.广义数组,即与类型无关的数组,具有与数组相同的所有操作. 那么,你或许要问:既然C++语言本身已提供了一个序列式容器array,为什么还要 ...

  9. Java容器之Map接口

    Map 接口: 1. 实现 Map 接口的类是用来存储键-值(key-value)对: 2. Map 接口的实现类有 HashMap 和 TreeMap 等: 3. Map 类中存储的键-值对,通过键 ...

随机推荐

  1. 洛谷P4556 雨天的尾巴 线段树

    正解:线段树合并 解题报告: 传送门! 考虑对树上的每个节点开一棵权值线段树,动态开点,记录一个max(num,id)(这儿的id,define了一下,,,指的是从小到大排QAQ 然后修改操作可以考虑 ...

  2. 【python基础】常用的内置函数

    python基础之内置函数 参考: http://www.runoob.com/python/python-built-in-functions.html -zip() zip函数接受任意多个(包括0 ...

  3. Linux 命令locate

    原文:https://blog.csdn.net/liang19890820/article/details/53285624 简述 locate 可以很快速的搜寻档案系统内是否有指定的档案.其方法是 ...

  4. 28-1-LTDC显示中英文

    1.字符编码 由于计算机只能识别 0 和 1,文字也只能以 0 和 1 的形式在计算机里存储,所以我们需要对文字进行编码才能让计算机处理,编码的过程就是规定特定的 01 数字串表示特定的文字,最简单的 ...

  5. Linux下Redis的安装与启动

    一. 进入目录(我们准备将redis装入opt文件夹) $ cd /opt/ 二.下载redis压缩包 $ wget http://download.redis.io/releases/redis-4 ...

  6. Navicat工具的使用 1

    Navicat 在生产环境中操作MySQL数据库还是推荐使用命令行工具mysql,但在我们自己开发测试时,可以使用可视化工具Navicat,以图形界面的形式操作MySQL数据库 官网下载:https: ...

  7. android下的样式

    android中控件,假如我们把样式都写死在控件的配置文件上的话.一旦改动可谓牵一发而动千军.那么我们能够把样式写在style.xml文件里.然后引用,在API14以上版本号. 该文件位于values ...

  8. MySQL数据库之part1

    一.初始数据库 链接:http://www.cnblogs.com/linhaifeng/articles/7126847.html 一.MySQL介绍 1.MySQL是什么 MySQL是一个关系型数 ...

  9. 机器人meta标签和X-Robots-Tag HTTP标头规格

    抽象 本文档详细介绍了页级索引设置如何让您控制Google如何通过搜索结果提供内容.您可以通过在(X)HTML页面或HTTP标头中包含元标记来指定这些标记. 笔记 请注意,只有当抓取工具被允许访问包含 ...

  10. python tkinter Treeview 事件绑定

    def trefun(event): sels= event.widget.selection()#event.widget获取Treeview对象,调用selection获取选择对象名称 for i ...