C++中的STL模板库的功能可谓相当强大。今天我们来简单说一下set和map的使用方法。

1.pair

我们先来说一下pair。pair定义在头文件<utility>中,其本身相当于一个已经重定义过的,有两个元素的结构体。它始终以前一个元素(first)为第一关键字,后一个元素(second)为第二关键字。在set或是其他STL容器中使用的时候自动进行按此排序。

pair的定义很简单,定义如下:

pair <int,int> q;

当然里面的数据类型可以改变,后面的变量名也可以任意改变。

或者你可以使用make_pair来新建一个pair,比如:

make_pair(s,t);

在新建pair的时候可以直接赋值,有两种方法,第一种如下:

pair <int,string> p1(,"Hello");

就是在定义的pair的名称后面打上括号,里面直接把值传进去。

第二种如下:

pair <int,string> p2 = make_pair(,"World");

这样的话就是使用一次makepair来对pair赋初值了。

看起来很简单。这样我们就可以在STL中使用pair这种数据结构类型,以进行各种复杂的操作……而在向里面压入pair元素的时候,只要加一个make_pair就可以了。

2.map

map本身是键值(key)和映射值(value)的一个映射。其中key和value可以选择任意数据类型。

(1)创建一个map

这里使用最简单的一种方法,就是直接定义一个map,在里面写上key和value的类型,再定义map的名字。

map <int,int> mp;

(2)向map中添加元素

第一种是直接使用map的下标进行添加,就像使用数组一样。比如:

for(int i = ;i <= n;i++) mp[i] = i * ;

第二种是使用insert函数,将一个pair元素进行插入。比如:

for(int i = ;i <= ;i++) mp.insert(make_pair(i,i*));

以及还有许多神奇的添加方式,在这里不一一讲述了……

(3)在map中查找元素

如果要直接查找元素在map中出现过多少次,那么可以使用count函数,比如:

    map <int,int> mp;
rep(i,,) mp.insert(make_pair(i,i*));
if(mp.count()) printf("Yes\n");

注意这里的count是直接查找键值(key)。

而且因为map中会自动对相同键值去重……所以count相当于只会告诉你这个元素是否有出现过。如果想使用count计算元素出现次数可以使用multimap。

map还有find()函数,可以返回指向所查找元素的迭代器,如果没有此元素就返回指向map尾部的迭代器。

比如:

map <int,int> :: iterator itf;
itf = mp.find();
if(itf != mp.end()) itf->second = ;

注意因为itf是一个迭代器(实际上是指针),所以我们使用了->,如果不愿意使用的话,也可以写成:

(*itf).second

最暴力的方式就是直接在map中用迭代器遍历,比如这样:

map <int,int> :: iterator it;
for(it = mp.begin();it != mp.end();it++) printf("%d->%d\n",it->first,it->second);

因为在map中元素的地址是相连的,所以直接it++即可。如果不愿意用->就使用上面的写法。

还有非常强劲的查找方式,那就是直接使用lowerbound和upperbound。这里要提一下map里面的排序,他是自动按key值从小到大排序,也就是说不可以对map使用sort。

lowerbound和upperbound与平时在数组上的用法都是一样的,一般来说支持key值查找(value作为第二关键字可不可行我还不知道……)一般来讲,我们映射都是一一映射,所以key值应该都是唯一的,直接在key值上查找就可以了。

特别的,如果lower/upperbound找不到元素的话,返回指向容器末尾的迭代器。

(返回的类型如果你开了代码补全可以看到……不过很影响码速)

(4)map中删除元素

删除元素一般来说有三种操作。第一种是直接使用erase函数往里面传实际值,比如:

mp.erase();

第二种就是向里面传一个迭代器,比如:

mp.erase(mp.begin());//显然begin函数返回的是一个迭代器!!

第三种就是传两个迭代器,注意这样删除的是一个左闭右开的区间,比如:

    map <int,int> mp;
rep(i,,) mp.insert(make_pair(i,i));
map <int,int> :: iterator itf;
itf = mp.upper_bound();
mp.erase(mp.begin(),itf);

这样删完之后,你会发现元素还剩15~19,(15没有被删去),用upperbound的话就是16~19了。

这些操作已经基本够用了……还有一个很厉害的swap。这里的swap函数直接交换的是两个map容器,而不是元素。

(下面代码是偷来的)

#include <map>
#include <iostream> using namespace std; int main( )
{
map <int, int> m1, m2, m3;
map <int, int>::iterator m1_Iter; m1.insert ( pair <int, int> ( , ) );
m1.insert ( pair <int, int> ( , ) );
m1.insert ( pair <int, int> ( , ) );
m2.insert ( pair <int, int> ( , ) );
m2.insert ( pair <int, int> ( , ) );
m3.insert ( pair <int, int> ( , ) ); cout << "The original map m1 is:";
for ( m1_Iter = m1.begin( ); m1_Iter != m1.end( ); m1_Iter++ )
cout << " " << m1_Iter->second;
cout << "." << endl; // This is the member function version of swap
//m2 is said to be the argument map; m1 the target map
m1.swap( m2 ); cout << "After swapping with m2, map m1 is:";
for ( m1_Iter = m1.begin( ); m1_Iter != m1.end( ); m1_Iter++ )
cout << " " << m1_Iter -> second;
cout << "." << endl;
cout << "After swapping with m2, map m2 is:";
for ( m1_Iter = m2.begin( ); m1_Iter != m2.end( ); m1_Iter++ )
cout << " " << m1_Iter -> second;
cout << "." << endl;
// This is the specialized template version of swap
swap( m1, m3 ); cout << "After swapping with m3, map m1 is:";
for ( m1_Iter = m1.begin( ); m1_Iter != m1.end( ); m1_Iter++ )
cout << " " << m1_Iter -> second;
cout << "." << endl; system("pause");
}

就是这样啦!

3.set

set即集合,内部是使用红黑树实现的(这么强劲的数据结构蒟蒻学不会QAQ)。不过set的操作还是非常值得学一学的。

(1)创建一个set。

set <int> q;

这是最简单的写法,里面的变量类型是任意的,比如什么pair啦或者是自己定义的结构体。

注意set在你没有进行重载运算符之前,默认是一个小根堆,而且会自动去重。

(2)向set里面插入元素

插入元素好像有好多好多奇妙的方法……不过我还是说最简单的吧,就是直接使用insert函数(set可不再支持用下标插入函数了)比如:

q.insert();//这是int版本的
q.insert((node){a,b,c})//如果你自定义一个结构体,就可以这么传(和平时往队列里面压一样)

(3)在set中查找元素

这里面好多函数在map中都介绍过了,而且在set中的用法和在map中基本一样,比如count,find等等。

不过,我们可以对结构体进行运算符重载,之后就可以愉悦的使用lowerbound对你想要的东西进行查找。

支持多关键字,多种排序方式,我们举个例子。

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<iostream>
#include<set>
#include<vector>
#include<utility>
#include<map>
#define rep(i,a,n) for(int i = a;i <= n;i++)
#define per(i,n,a) for(int i = n;i >= a;i--)
#define enter putchar('\n') struct node
{
int sum,val;
bool operator < (const node &g)const
{
if(sum == g.sum) return val > g.val;
return sum < g.sum;
}
}
set <node> q;
int main()
{
for(int i = ;i <= n;i++) q.insert((node){a,b,c});
set <node> :: iterator it;
it = q.lower_bound((node){,,});
//这样就可以查找了
return ;
}

非常强力的查找方式。然后……注意重载运算符只能重载小于号。

注意lowerbound返回第一个大于等于查找键值的元素,而upperbound返回的是最后一个大于等于查找键值的元素。

(4)在set中删除元素

这些函数的用法和map基本是一样的,不加以赘述。

具体的操作也就是这些了……set同样是需要用迭代器来加以访问。

希望能帮助到大家。

C++ set和map的简单使用的更多相关文章

  1. Java内存缓存-通过Map定制简单缓存

    缓存 在程序中,缓存是一个高速数据存储层,其中存储了数据子集,且通常是短暂性存储,这样日后再次请求此数据时,速度要比访问数据的主存储位置快.通过缓存,可以高效地重用之前检索或计算的数据. 为什么要用缓 ...

  2. set和map的简单用法

    .set(集合)map(映射)都属于关联类容器 都支持查询一个元素是否存在并能够有效地获取元素. set集合的元素总是从小到大排列,set集合通过二分查找树实现.它具备以下两个特点: ①:独一无二的元 ...

  3. Map的简单语法

    package jaxpsax; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; i ...

  4. HDU1004 Let the Balloon Rise(map的简单用法)

    Let the Balloon Rise Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others ...

  5. GO的MAP字典简单用法示例

    package main import "fmt" type PersonInfo struct { ID string Name string Address string } ...

  6. scala map操作 简单总结

    在函数式编程中有一个核心的概念之一是转换,所以大部份支持函数式编程语言,都支持一种叫map()的动作,这个动作是可以帮你把某个容器的内容,套上一些动作之后,变成另一个新的容器. 现在我们考虑如何用Op ...

  7. leetcode 249 250 set和map的简单用法

    leetcode249,利用了STL中的set class Solution { public: vector<int> intersection(vector<int>&am ...

  8. js中的Map对象的简单示例

    es6提供一个对象Map, 其功能类似于java中的Map, 下面是java中的Map和js中的Map的简单对比: js中的Map.set()相当于java中的Map.put(), js中的Map.s ...

  9. C++ map的基本操作和使用

    原文地址:http://blog.sina.com.cn/s/blog_61533c9b0100fa7w.html Map是c++的一个标准容器,她提供了很好一对一的关系,在一些程序中建立一个map可 ...

随机推荐

  1. LeetCode:926. 将字符串翻转到单调递增

    暴力法超时:思想:动态规划 public int minFlipsMonoIncrb(String S) { int result = S.length(); for (int i = 0; i &l ...

  2. RecyclerView的万能切割线

    效果图: 用法: 加入默认切割线:高度为2px.颜色为灰色 mRecyclerView.addItemDecoration(new RecycleViewDivider(mContext, Linea ...

  3. electron 开发拆坑总结

    electron 总结 前言 有一个web项目需要用客户端来包装一下 项目的主要业务都在服务器上 所以项目的大多数功能都用url 地址来访问: 客户端登陆界面在本地 打包客户端的本地登陆界面 做为登陆 ...

  4. EF Core使用SQL调用返回其他类型的查询 ASP.NET Core 2.0 使用NLog实现日志记录 CSS 3D transforms cSharp:use Activator.CreateInstance with an Interface? SqlHelper DBHelper C# Thread.Abort方法真的让线程停止了吗? 注意!你的Thread.Abort方法真

    EF Core使用SQL调用返回其他类型的查询   假设你想要 SQL 本身编写,而不使用 LINQ. 需要运行 SQL 查询中返回实体对象之外的内容. 在 EF Core 中,执行该操作的另一种方法 ...

  5. 《Java虚拟机原理图解》4.JVM机器指令集

    0. 前言 Java虚拟机和真实的计算机一样,执行的都是二进制的机器码:而我们将.java 源码编译成.class 文件,class文件便是Java虚拟机可以认识的二进制机器码,Java可以识别cla ...

  6. 这样看ACM是不是更好?

    如果搞ACM只是为了拿奖,为了保研,这样太功利,整个过程都会变得没意思.我说过我同时看中过程和结果. 其实ACM解题也不是那么没意思,每次AC都有一种非常棒的成就感,每个题目就像是一个解谜游戏,完成了 ...

  7. Nova镜像使用方法

    Nova中的虚拟机可以从镜像.卷.卷快照等启动,一般装完OpenStack时,环境中既没有镜像也没有卷,这时候往往 需要上传一些已有的镜像,或者上传ISO文件来安装虚拟机系统.这个文档主要描述如何上传 ...

  8. Redis 事务及其应用

    参考: http://www.runoob.com/redis/redis-transactions.html https://www.cnblogs.com/qlshine/p/5958504.ht ...

  9. window批处理-5 start

    作用 又一次启动一个单独窗体.在新窗体中运行命令 格式 start [/w] FileName demo bat: @echo off echo 在新窗体中打开txt文件.并等待新窗体正常退出(exi ...

  10. bzoj 1088 简单dfs

    /* 题意:给你一列仅仅能取0和1的数. 限制:每3个相邻的数的值固定,开头和结尾仅仅限制两个数 求:有多少种组合方案 解:搜索,在开头和结尾再加一个仅仅能取零的数,直接推断是否符合条件就可以 */ ...