map iterator pair priority_queue C++

参考:https://zhuanlan.zhihu.com/p/127860466
参考:https://blog.csdn.net/google19890102/article/details/51720305
参考:http://c.biancheng.net/view/338.html C++迭代器(STL迭代器)iterator详解
参考:https://blog.csdn.net/hnjzsyjyj/article/details/108929993 用pair做优先队列priority_queue元素的例子

map

map简介

map是STL(中文标准模板库)的一个关联容器。

  • 可以将任何基本类型映射到任何基本类型。如int array[100]事实上就是定义了一个int型到int型的映射。
  • map提供一对一的数据处理,key-value键值对,其类型可以自己定义,第一个称为关键字,第二个为关键字的值
  • map内部是自动排序的

map的用法

  • 引入包
#include<map>
  • map对象的定义和初始化
    map是键-值对的组合,有以下的一些定义的方法:

  • map<k, v> m;

  • map<k, v> m(m2);

  • map<k, v> m(b, e);
    上述第一种方法定义了一个名为m的空的map对象;第二种方法创建了m2的副本m;第三种方法创建了map对象m,并且存储迭代器b和e范围内的所有元素的副本。
    map的value_type是存储元素的键以及值的pair类型,键为const。

map容器内元素的访问

  • 通过下标进行访问
    如:maps[‘c’]=5;
  • 通过迭代器进行访问
    map可以使用it->first来访问键,使用it->second访问值
#include<map>
#include<iostream>
using namespace std;
int main()
{
   map<char,int>maps;
   maps['d']=10;
   maps['e']=20;
   maps['a']=30;
   maps['b']=40;
   maps['c']=50;
   maps['r']=60;
   for(map<char,int>::iterator it=mp.begin();it!=mp.end();it++)
   {
       cout<<it->first<<" "<<it->second<<endl;
   }
   return 0;
}

map的常用用法

  • map中元素的插入
    在map中元素有两种插入方法:

    • 使用下标
    • 使用insert函数

    在map中使用下标访问不存在的元素将导致在map容器中添加一个新的元素。

    insert函数的插入方法主要有如下:

    • m.insert(e)
    • m.insert(beg, end)
    • m.insert(iter, e)

    上述的e一个value_type类型的值。beg和end标记的是迭代器的开始和结束。

    两种插入方法如下面的例子所示:

    #include <stdio.h>
    #include <map>
    using namespace std;
    
    int main(){
            map<int, int> mp;
            for (int i = 0; i < 10; i ++){
                    mp[i] = i;
            }
            for (int i = 10; i < 20; i++){
                    mp.insert(make_pair(i, i));
            }
            map<int, int>::iterator it;
            for (it = mp.begin(); it != mp.end(); it++){
                    printf("%d-->%d\n", it->first, it->second);
            }
            return 0;
    }
    
  • maps.find() 查找一个元素
    注意:上述采用下标的方法读取map中元素时,若map中不存在该元素,则会在map中插入。

因此,若只是查找该元素是否存在,可以使用函数count(k),该函数返回的是k出现的次数;若是想取得key对应的值,可以使用函数find(k)`,该函数返回的是指向该元素的迭代器。

map<string,int>::iterator it;
it=maps.find("123");
  • maps.clear()清空
  • maps.erase()删除一个元素
//迭代器刪除
it = maps.find("123");
maps.erase(it);

//关键字删除
int n = maps.erase("123"); //如果刪除了返回1,否则返回0

//用迭代器范围刪除 : 把整个map清空
maps.erase(maps.begin(), maps.end());
//等同于mapStudent.clear()
  • maps.szie()长度
  • maps.begin()返回指向map头部的迭代器
  • maps.end()返回指向map末尾的迭代器
  • maps.rbegin()返回指向map尾部的逆向迭代器
  • maps.rend()返回指向map头部的逆向迭代器
  • maps.empty()判断其是否为空
  • maps.swap()交换两个map

迭代器iterator

要访问顺序容器和关联容器中的元素,需要通过“迭代器(iterator)”进行。迭代器是一个变量,相当于容器和操纵容器的算法之间的中介。迭代器可以指向容器中的某个元素,通过迭代器就可以读写它指向的元素。从这一点上看,迭代器和指针类似。

四种迭代器

  • 正向迭代器,定义方法如下:
容器类名::iterator  迭代器名;
  • 常量正向迭代器,定义方法如下:
容器类名::const_iterator  迭代器名;
  • 反向迭代器,定义方法如下:
容器类名::reverse_iterator  迭代器名;
  • 常量反向迭代器,定义方法如下:
容器类名::const_reverse_iterator  迭代器名;

迭代器用法示例

通过迭代器可以读取它指向的元素,*迭代器名就表示迭代器指向的元素。通过非常量迭代器还能修改其指向的元素。
迭代器都可以进行++操作。反向迭代器和正向迭代器的区别在于:

  • 对正向迭代器进行++操作时,迭代器会指向容器中的后一个元素;
  • 而对反向迭代器进行++操作时,迭代器会指向容器中的前一个元素。

下面的程序演示了如何通过迭代器遍历一个 vector 容器中的所有元素。

#include <iostream>
#include <vector>
using namespace std;
int main()
{
    vector<int> v;  //v是存放int类型变量的可变长数组,开始时没有元素
    for (int n = 0; n<5; ++n)
        v.push_back(n);  //push_back成员函数在vector容器尾部添加一个元素
    vector<int>::iterator i;  //定义正向迭代器
    for (i = v.begin(); i != v.end(); ++i) {  //用迭代器遍历容器
        cout << *i << " ";  //*i 就是迭代器i指向的元素
        *i *= 2;  //每个元素变为原来的2倍
    }
    cout << endl;
    //用反向迭代器遍历容器
    for (vector<int>::reverse_iterator j = v.rbegin(); j != v.rend(); ++j)
        cout << *j << " ";
    return 0;
}

程序的输出结果是:

0 1 2 3 4
8 6 4 2 0

后置++要多生成一个局部对象 tmp,因此执行速度比前置的慢。同理,迭代器是一个对象,STL 在重载迭代器的++运算符时,后置形式也比前置形式慢。在次数很多的循环中,++i和i++可能就会造成运行时间上可观的差别了。因此,本教程在前面特别提到,对循环控制变量i,要养成写++i不写i++的习惯。
注意,容器适配器 stackqueuepriority_queue 没有迭代器。容器适配器有一些成员函数,可以用来对元素进行访问。

迭代器的功能分类

不同容器的迭代器,其功能强弱有所不同。容器的迭代器的功能强弱,决定了该容器是否支持 STL 中的某种算法。例如,排序算法需要通过随机访问迭代器来访问容器中的元素,因此有的容器就不支持排序算法。

常用的迭代器按功能强弱分为输入、输出、正向、双向、随机访问五种,这里只介绍常用的三种

  1. 正向迭代器。假设 p是一个正向迭代器,则p支持以下操作:++pp++*p。此外,两个正向迭代器可以互相赋值,还可以用==!=运算符进行比较。
  2. 双向迭代器。双向迭代器具有正向迭代器的全部功能。除此之外,若 p 是一个双向迭代器,则--pp--都是有定义的。--p使得 p朝和++p相反的方向移动。
  3. 随机访问迭代器。随机访问迭代器具有双向迭代器的全部功能。若 p 是一个随机访问迭代器,i 是一个整型变量或常量,则 p 还支持以下操作:
    • p+=i:使得 p 往后移动 i 个元素。
    • p-=i:使得 p 往前移动 i 个元素。
    • p+i:返回 p 后面第 i 个元素的迭代器。
    • p-i:返回 p 前面第 i 个元素的迭代器。
    • p[i]:返回 p 后面第 i 个元素的引用。

此外,两个随机访问迭代器 p1、p2 还可以用 <、>、<=、>= 运算符进行比较。p1<p2的含义是:p1 经过若干次(至少一次)++操作后,就会等于 p2。其他比较方式的含义与此类似。

对于两个随机访问迭代器 p1、p2,表达式p2-p1也是有定义的,其返回值是 p2 所指向元素和 p1 所指向元素的序号之差(也可以说是 p2 和 p1 之间的元素个数减一)。

表1所示为不同容器的迭代器的功能。

容器迭代器功能
vector随机访问
deque随机访问
list双向
set / multiset双向
map / multimap双向
stack不支持迭代器
queue不支持迭代器
priority_queue不支持迭代器

迭代器的辅助函数

STL 中有用于操作迭代器的三个函数模板,它们是:

  • advance(p, n):使迭代器 p 向前或向后移动 n 个元素。
  • distance(p, q):计算两个迭代器之间的距离,即迭代器 p 经过多少次 + + 操作后和迭代器 q 相等。如果调用时 p
    已经指向 q 的后面,则这个函数会陷入死循环
  • iter_swap(p, q):用于交换两个迭代器 p、q 指向的值

要使用上述模板,需要包含头文件 algorithm。下面的程序演示了这三个函数模板的 用法.

#include <list>
#include <iostream>
#include <algorithm> //要使用操作迭代器的函数模板,需要包含此文件
using namespace std;
int main()
{
    int a[5] = { 1, 2, 3, 4, 5 };
    list <int> lst(a, a+5);
    list <int>::iterator p = lst.begin();
    advance(p, 2);  //p向后移动两个元素,指向3
    cout << "1)" << *p << endl;  //输出 1)3
    advance(p, -1);  //p向前移动一个元素,指向2
    cout << "2)" << *p << endl;  //输出 2)2
    list<int>::iterator q = lst.end();
    q--;  //q 指向 5
    cout << "3)" << distance(p, q) << endl;  //输出 3)3
    iter_swap(p, q); //交换 2 和 5
    cout << "4)";
    for (p = lst.begin(); p != lst.end(); ++p)
        cout << *p << " ";
    return 0;
}

程序的输出结果是:

1) 3
2) 2
3) 3
4) 1 5 3 4 2

pair

pair将两个数据(经常为不同数据类型)组合成一组数据。
pair的实现是一个结构体,主要的两个成员变量是firstsecond

pair的常见构造方法

1.pair<T1, T2> p1;
创建一个空的pair对象,它的两个元素分别是T1和T2类型,然后赋值初始化。实例如下

#include<bits/stdc++.h>
using namespace std;
int main() {
	pair<int,double> p1;
	p1.first=1;
	p1.second=2.5;
	cout<<p1.first<<" "<<p1.second<<endl;
	return 0;
}

输出为:1 2.5

2.pair<T1, T2> p1(v1, v2);
创建一个pair对象,它的两个元素分别是T1和T2类型,其中first成员初始化为v1,second成员初始化为v2。实例如下:

#include<bits/stdc++.h>
using namespace std;
int main() {
	pair<string, double> p2("Algorithm", 56.8);
	cout<<p2.first<<" "<<p2.second<<endl;
	return 0;
}

输出为:Algorithm 56.8

3.make_pair(v1, v2);
以v1和v2的值创建一个新的pair对象,其元素类型分别是v1和v2的类型。实例如下

#include<bits/stdc++.h>
using namespace std;
 
int main(){
	int age=8;
	string name="James";
	pair<int,string> p3;
	p3=make_pair(age,name);
	cout<<p3.first<<" "<<p3.second<<endl;
	return 0;
}

输出为:8 James

优先队列priority_queue

优先队列priority_queue,本质上是用实现的,可用于实现堆优化的Dijkstra算法

基本语法

  • 升序队列,小根堆:priority_queue <int,vector<int>,greater<int> > p;
  • 降序队列,大根堆:priority_queue <int,vector<int>,less<int> >q;
  • 对于基础数据类型,默认是大顶堆:priority_queue r; //等同于 priority_queue<int,vector, less > r;

基本操作

优先队列priority_queue队列基本操作相同:

  • top 访问队头元素
  • empty 队列是否为空
  • size 返回队列内元素个数
  • push 插入元素到队尾 (并排序)
  • emplace 原地构造一个元素并插入队列
  • pop 弹出队头元素
  • swap 交换内容

优先队列priority_queue的常见实现如下:

#include<bits/stdc++.h>
using namespace std;
int main(){
	priority_queue<int> a;
	priority_queue<int,vector<int>,greater<int> > b;
	priority_queue<string> c;
	for (int i=0;i<5;i++){
		a.push(i);
		b.push(i);
	}
	
	while (!a.empty()){
		cout<<a.top()<<" ";
		a.pop();
	}
	cout<<endl;
 
	while(!b.empty()){
		cout<<b.top()<<" ";
		b.pop();
	}
	cout<<endl;
 
	c.push("abc");
	c.push("abcd");
	c.push("cbd");
	while (!c.empty()){
		cout<<c.top()<<" ";
		c.pop();
	}
	cout<<endl;
	return 0;
}

输出为:

4 3 2 1 0
0 1 2 3 4
cbd abcd abc
#include<bits/stdc++.h>
using namespace std;
 
int main() {
	priority_queue<pair<int, int> > a;
	pair<int,int> b(1,5);
	pair<int,int> d(1,2);
	pair<int,int> c(6,1);
 
	a.push(d);
	a.push(c);
	a.push(b);
 
	while (!a.empty()) {
		cout<<a.top().first<<" "<<a.top().second<<endl;
		a.pop();
	}
 
	return 0;
}

【程序输出】
pair的比较规则:先比较第一个元素,第一个相等比较第二个。

6 1
1 5
1 2
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值