关联数组map和关联容器set的用法和二者的区别

本文详细介绍了C++ STL中的Map和Set容器,包括构造、数据插入、遍历等核心功能,并对比了两者之间的主要区别。

map(也叫关联数组):

       map是STL的一个关联容器,它提供一对一(其中第一个可以称为关键字,每个关键字只能在map中出现一次,第二个可能称为该关键字的值)的数据处理能力,由于这个特性,它完成有可能在我们处理一对一数据的时候,在编程上提供快速通道。这里说下map内部数据的组织,map内部自建一颗红黑树(一种非严格意义上的平衡二叉树),这颗树具有对数据自动排序的功能,所以在map内部所有的数据都是有序的,后边我们会见识到有序的好处。
 
1. map的构造函数
map<int,string> maphai;
map<char,int> maphai;
map<string,char> mapstring;
map<string,int> mapstring;
map<int,char>mapint;
map<char,string>mapchar;
 
2. 数据的插入
在构造map容器后,我们就可以往里面插入数据了。这里讲三种插入数据的方法:
第一种:用insert函数插入pair数据,
#include <map>
#include <string>
#include <iostream>
Using namespace std;
Int main()
{
Map<int,string> mapStudent;
mapStudent.insert(pair<int,string>(1,“student_one”));
mapStudent.insert(pair<int,string>(2,“student_two”));
mapStudent.insert(pair<int,string>(3,“student_three”));
map<int,string>::iterator iter;
for(iter = mapStudent.begin(); iter != mapStudent.end(); iter++)
{
Cout<<iter->first<<” ”<<iter->second<<end;
}
}
 
第二种:用insert函数插入value_type数据,下面 举例 说明
#include <map>
#include <string>
#include <iostream>
Using namespace std;
Int main()
{
Map<int,string> mapStudent;
mapStudent.insert(map<int,string>::value_type (1,“student_one”));
mapStudent.insert(map<int,string>::value_type (2,“student_two”));
mapStudent.insert(map<int,string>::value_type (3,“student_three”));
map<int,string>::iterator iter;
for(iter = mapStudent.begin(); iter != mapStudent.end(); iter++)
{
Cout<<iter->first<<” ”<<iter->second<<end;
}
}
 
第三种:用 数组 方式插入数据,下面举例说明
#include <map>
#include <string>
#include <iostream>
Using namespace std;
Int main()
{
Map<int,string> mapStudent;
mapStudent[1] = “student_one”;
mapStudent[2] = “student_two”;
mapStudent[3] = “student_three”;
map<int,string>::iterator iter;
for(iter = mapStudent.begin(); iter != mapStudent.end(); iter++)
{
Cout<<iter->first<<” ”<<iter->second<<end;
}
}
       以上三种用法,虽然都可以实现数据的插入,但是它们是有区别的,当然了第一种和第二种在效果上是完成一样的,用insert函数插入数据,在数据的插入上涉及到集合的唯一性这个概念,即当map中有这个关键字时,insert操作是插入数据不了的,但是用 数组 方式就不同了,它可以覆盖以前该关键字对应的值,用程序说明
      mapStudent.insert(map<int,string>::value_type (1,“student_one”));
      mapStudent.insert(map<int,string>::value_type (1,“student_two”));
      上面这两条语句执行后,map中1这个关键字对应的值是“student_one”,第二条语句并没有生效,那么这就涉及到我们怎么知道insert语句是否插入成功的问题了,可以用pair来获得是否插入成功,程序如下
      pair<map<int,string>::iterator,bool> Insert_Pair;
      Insert_Pair = mapStudent.insert(map<int,string>::value_type (1,“student_one”));
      我们通过pair的第二个变量来知道是否插入成功,它的第一个变量返回的是一个map的迭代器,如果插入成功的话Insert_Pair.second应该是true的,否则为false。
 
下面给出完成代码,演示插入成功与否问题
#include <map>
#include <string>
#include <iostream>
Using namespace std;
Int main()
{
Map<int,string> mapStudent;
Pair<map<int,string>::iterator,bool> Insert_Pair;
Insert_Pair = mapStudent.insert(pair<int,string>(1,“student_one”));
If(Insert_Pair.second == true)
{
Cout<<”Insert Successfully”<<endl;
}
Else
{
Cout<<”Insert Failure”<<endl;
}
Insert_Pair = mapStudent.insert(pair<int,string>(1,“student_two”));
If(Insert_Pair.second == true)
{
Cout<<”Insert Successfully”<<endl;
}
Else
{
Cout<<”Insert Failure”<<endl;
}
map<int,string>::iterator iter;
for(iter = mapStudent.begin(); iter != mapStudent.end(); iter++)
{
Cout<<iter->first<<” ”<<iter->second<<end;
}
}
大家可以用如下程序,看下用数组插入在数据覆盖上的效果
#include <map>
#include <string>
#include <iostream>
Using namespace std;
Int main()
{
Map<int,string> mapStudent;
mapStudent[1] = “student_one”;
mapStudent[1] = “student_two”;
mapStudent[2] = “student_three”;
map<int,string>::iterator iter;
for(iter = mapStudent.begin(); iter != mapStudent.end(); iter++)
{
Cout<<iter->first<<” ”<<iter->second<<end;
}
}
3. map的大小
在往map里面插入了数据,我们怎么知道当前已经插入了多少数据呢,可以用size函数,用法如下:
Int nSize = mapStudent.size();
4. 数据的遍历
这里也提供三种方法,对map进行遍历
第一种:应用前向迭代器,上面举例程序中到处都是了,略过不表
第二种:应用反相迭代器,下面举例说明,要体会效果,请自个动手运行程序
#include <map>
#include <string>
#include <iostream>
Using namespace std;
Int main()
{
Map<int,string> mapStudent;
mapStudent.insert(pair<int,string>(1,“student_one”));
mapStudent.insert(pair<int,string>(2,“student_two”));
mapStudent.insert(pair<int,string>(3,“student_three”));
map<int,string>::reverse_iterator iter;
for(iter = mapStudent.rbegin(); iter != mapStudent.rend(); iter++)
{
Cout<<iter->first<<” ”<<iter->second<<end;
}
}
第三种:用数组方式,程序说明如下
#include <map>
#include <string>
#include <iostream>
Using namespace std;
Int main()
{
Map<int,string> mapStudent;
mapStudent.insert(pair<int,string>(1,“student_one”));
mapStudent.insert(pair<int,string>(2,“student_two”));
mapStudent.insert(pair<int,string>(3,“student_three”));
int nSize = mapStudent.size()
//此处有误,应该是 for(int nIndex = 1; nIndex <= nSize; nIndex++)
//by rainfish
for(int nIndex = 0; nIndex < nSize; nIndex++)
{
Cout<<mapStudent[nIndex]<<end;
}
}
 
set关联容器:
set是C++标准库中的一种关联容器。所谓关联容器就是通过键(key)来读取和修改元素。与 map 关联容器不同,它只是单纯键的集合。
set容器的每一个键只能对应一个元素,即不存在键相同的不同元素。
示例代码:
#include <iostream>
#include <set>
#include <vector>
int main(int argc, char* argv[]) {
std::vector<int>vec;
for(std::vector<int>::size_type i = 0; i < 10; ++i) {
vec.push_back(i);
vec.push_back(i);
}
std::cout<< "vector : " << std::endl;
for(std::vector<int>::iterator it = vec.begin(); it != vec.end(); ++it) {
std::cout<< *it << ",";
}
std::cout<< std::endl;
std::set<int>st(vec.begin(), vec.end());
std::cout<< "set : " << std::endl;
for(std::set<int>::iterator it = st.begin(); it != st.end(); ++it) {
std::cout<< *it << ",";
}
std::cout<< std::endl;
return 0;
}
输出结果:
vector :
0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9
set :
0,1,2,3,4,5,6,7,8,9
创建了一个int型的 vector 容器,存储20个数据,0~9每个数字都出现了两次。用整个 vector 初始化 一个int型set容器,这个set容器却只有10个元素,0~9每个数字只出现一次。证实了set容器的每一个键只能对应一个元素。

编辑本段添加元素

可以使用insert操作向set容器添加元素。
示例代码:
#include <iostream>
#include <set>
#include <vector>
int main(int argc, char* argv[]) {
std::vector<int>vec;
vec.push_back(1);
vec.push_back(2);
std::set<int>st;
st.insert(10);
st.insert(vec.begin(),vec.end());
std::cout<< "set : ";
for(std::set<int>::iterator it = st.begin(); it != st.end(); ++it) {
std::cout<< *it << " ";
}
std::cout<< std::endl;
return 0;
}
输出结果:
set : 1 2 10
insert()的参数既可以是一个键,也可以是一对 迭代器 ,它们都可以实现向set容器中添加元素,只不过函数的返回值不同。另外,可以看出向set容器中添加元素后,它会自动排序。

编辑本段获取元素

与map容器不同,set容器不支持下标操作访问元素。
使用count()函数可以查询元素是否存在,如果查询的元素存在则返回1,反之则0。使用find()函数,如果查询的元素存在则返回指向该元素的 迭代器 ,反之则返回超出末端 迭代器
示例代码:
#include <iostream>
#include <set>
int main(int argc, char* argv[]) {
std::set<int> st;
st.insert(1);
st.insert(5);
st.insert(10);
std::cout<< "count(5) : " << st.count(5) << std::endl;
std::cout<< "find(5): " << *st.find(5) << std::endl;
return 0;
}
输出结果:
count(5) : 1
find(5): 5
使用count()和find()函数查询同一元素5,count()函数返回的是该元素在set容器中的数量,find()函数则返回指向该元素的 迭代器 。需要注意的是,虽然使用find()函数可以返回指向该元素的 迭代器 ,但只能对其做读操作,任何试图修改键值的操作都是非法的。
 
二者的区别:
1、map容器是键/值对的集合,与 map 关联容器不同,set它只是单纯键的集合。
2、map容器支持下标操作符访问元素,map容器不同,set容器不支持下标操作访问元素。
 
参考网址:
下载方式:https://pan.quark.cn/s/a4b39357ea24 布线问题(分支限界算法)是计算机科学电子工程领域中一个广为人知的议题,它主要探讨如何在印刷电路板上定位两个节点间最短的连接路径。 在这一议题中,电路板被构建为一个包含 n×m 个方格的矩阵,每个方格能够被界定为可通行或不可通行,其核心任务是定位从初始点到最终点的最短路径。 分支限界算法是处理布线问题的一种常用策略。 该算法与回溯法有相似之处,但存在差异,分支限界法仅需获取满足约束条件的一个最优路径,并按照广度优先或最小成本优先的原则来探索解空间树。 树 T 被构建为子集树或排列树,在探索过程中,每个节点仅被赋予一次成为扩展节点的机会,且会一次性生成其全部子节点。 针对布线问题的解决,队列式分支限界法可以被采用。 从起始位置 a 出发,将其设定为首个扩展节点,并将与该扩展节点相邻且可通行的方格加入至活跃节点队列中,将这些方格标记为 1,即从起始方格 a 到这些方格的距离为 1。 随后,从活跃节点队列中提取队首节点作为下一个扩展节点,并将与当前扩展节点相邻且未标记的方格标记为 2,随后将这些方格存入活跃节点队列。 这一过程将持续进行,直至算法探测到目标方格 b 或活跃节点队列为空。 在实现上述算法时,必须定义一个类 Position 来表征电路板上方格的位置,其成员 row col 分别指示方格所在的行列。 在方格位置上,布线能够沿右、下、左、上四个方向展开。 这四个方向的移动分别被记为 0、1、2、3。 下述表格中,offset[i].row offset[i].col(i=0,1,2,3)分别提供了沿这四个方向前进 1 步相对于当前方格的相对位移。 在 Java 编程语言中,可以使用二维数组...
源码来自:https://pan.quark.cn/s/a4b39357ea24 在VC++开发过程中,对话框(CDialog)作为典型的用户界面组件,承担着与用户进行信息交互的重要角色。 在VS2008SP1的开发环境中,常常需要满足为对话框配置个性化背景图片的需求,以此来优化用户的操作体验。 本案例将系统性地阐述在CDialog框架下如何达成这一功能。 首先,需要在资源设计工具中构建一个新的对话框资源。 具体操作是在Visual Studio平台中,进入资源视图(Resource View)界面,定位到对话框(Dialog)分支,通过右键选择“插入对话框”(Insert Dialog)选项。 完成对话框内控件的布局设计后,对对话框资源进行保存。 随后,将着手进行背景图片的载入工作。 通常有两种主要的技术路径:1. **运用位图控件(CStatic)**:在对话框界面中嵌入一个CStatic控件,并将其属性设置为BST_OWNERDRAW,从而具备自主控制绘制过程的权限。 在对话框的类定义中,需要重写OnPaint()函数,负责调用图片资源并借助CDC对象将其渲染到对话框表面。 此外,必须合理处理WM_CTLCOLORSTATIC消息,确保背景图片的展示不会受到其他界面元素的干扰。 ```cppvoid CMyDialog::OnPaint(){ CPaintDC dc(this); // 生成设备上下文对象 CBitmap bitmap; bitmap.LoadBitmap(IDC_BITMAP_BACKGROUND); // 获取背景图片资源 CDC memDC; memDC.CreateCompatibleDC(&dc); CBitmap* pOldBitmap = m...
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值