vector、list、pair、unordered_map、unordered_set、stack、queue
参考文章:
(1)【apollo】泛型编程 与 STL
(2)c++ stack用法 入门必看 超详细
(3)C++中queue的用法(超详细,入门必看)
(4)C++——list的简介及使用
(5)C++中pair用法
(6)c++中map详解
(7)c++中unordered_map的用法的详述(包含unordered_map和map的区别)
(8)【总结】C++ 基础数据结构 —— STL之集合(set)用法详解
(9)C++常用语法——unordered_set
1 C++中vector用法
向量(vector):连续存储的元素
头文件包含:#include <vector>
1.1 Vector容器简介
(1)vector是将元素置于一个动态数组中加以管理的容器
(2)vector可以随机存取元素(支持索引值直接存取,用[ ]或at()方法)
(3)vector尾部添加或移除元素很快。但是在中间或头部插入、移除就很费时。
1.2 Vector对象的构造
① 默认构造:使用默认构造函数构造出来的vector对象的size为0
vector<int> vec;
vector<float> vec;
vector<string> vec;
class A {};
vector<A*> vec; // 用于存放A对象指针的vector容器
vector<A> vec; // 用于存放A对象的vector容器
② 带参数构造
int A[] = {0, 1, 2, 3, 4, 5};
vector<int> vecA(A, A + 5);
vector<int> vec(vecA.begin(), vecA.end());
vector<int> vec(vecA.begin(), vecA.begin() + 3);
vector<int> vec(n, 0);
vector<int> vecD(vecA);
vector v4 = v1;
③ Vector的赋值
vector.assign(beg, end); // 将[beg, end)数据拷贝赋值给本身
vector.assign(n, elem); // 将n个elem拷贝赋值给本身
vector& operator=(const vector& vec); // 重载等号操作符
vector.swap(vec); // 将vec与本身的元素互换
vector<int> vecA, vecB, vecC, vecD;
int aaa[] = {0, 1, 2, 3, 4};
vecA.assign(aaa, aaa + 5);
vecB.assign(vecA.begin(), vecA.end());
vecC.assign(3, 9);
vecD = vecA;
vecA.swap(vecD);
使用vector.assign()时,会将vector中原本的元素都清空,再执行赋值操作
///计算vector中的元素数量
vector.size() ;
///指向容器中的第一个元素的迭代器(指针)
vector.begin();
///指向容器中的最后一个元素的下一位的迭代器(指针),左闭右开
vector.end();
///a = {1,2,3,4,5,6,7};
vector.assign(a.begin()+2,vector.end()-1 )
///vector = {3,4,5,6};
④ Vector的大小、Vector的访问方式(查改)
vector.size(); // 返回容器中元素的个数
vector.empty(); // 判断容器是否为空
vector.resize(num); // 重新指定容器的长度为num,若容器变长,则以默认值0填充新位置,如果容器变短,则末尾超出容器长度的元素被删除
vector.resize(num, elem); // 重新指定容器的长度为num,若容器变长,则以elem填充新位置,如果容器变短,则末尾超出容器长度的元素被删除
下表法:访问vector容器中的元素,下标越界,可能会导致程序异常终止,且不会输出异常原因。但是使用STL中vector提供的访问方法就能够给出报错原因。
vector.at(idx); // 返回索引idx所指的数据,如果idx越界,抛出out_of_range异常
vec[idx]; // 返回索引idx所指的数据,越界运行会报错
vector<int> vecInt; // 1, 3, 5, 7, 9
vecInt.at(2) == vecInt[2]; // 5
vecInt.at(2) = 8; // 1, 3, 8, 7, 9
int if = vecInt.front(); // 1
int ib = vecInt.back(); // 9
vecInt.front() = 11; // 11, 3, 8, 7, 9
vecInt.back() = 19; // 11, 3, 8, 7, 19
⑤ vector的插入和 删除 (“增删”)
vector末尾添加和删除操作
vector<int> vec;
vec.push_back(1);
vec.push_back(2);
vec.pop_back();
vector的插入
⑥ 打印vector中的所有元素
vector<int> vec = {1, 2, 3, 4, 5};
for (int i = 0; i < vec.size(); i++) {
cout << vec[i] << " ";
}
⑦ vector容器中迭代器的基本使用
vector<int>::iterator iter = v.begin();
for (auto iter = v.begin(); iter != v.end(); iter++) *iter = 0;
2 C++中stack用法
2.1 基本操作
Stack:先进后出
包含头文件:#include <stack>
stack<int> stInt;
stack<float> stFloat;
stack<string> stString;
基本使用方法:
① push:往栈头添加元素
stack.push(elem);
② pop:往栈头移除第一个元素
stack.pop();
Tip:
- stack容器没有迭代器,不允许遍历。要想访问元素只有出栈这个方法
stack.pop()
函数删除栈顶元素,返回值为void,不会返回被删除的栈顶元素值- 使用
stack.top()
函数就能够得到栈顶元素,不会删除栈顶元素,通常top和pop两个相结合使用
③ empty:判断是否为空,若为空,返回值为true;否则为false
if (!stInt.empty()) {}
④ size:返回堆栈的大小
int size = stInt.size();
⑤ top:返回栈顶元素
2.2 从stack到string
栈中的数据是不允许随机访问的,就是不能像数组那样用下标访问,也不能遍历栈内的元素,这是很局限的。实际上,我们经常使用的string类型就是一种栈结构,但是我们可以通过下标访问元素。
string的栈相关的成员函数
empty() //堆栈为空则返回真
pop_back() //移除栈顶元素
push_back() //在栈顶增加元素
size() //返回栈中元素数目
back() //返回栈顶元素
#include <iostream>
#include <string> // string包括了一些字符串操作的库函数,但用string时是不用引入这个头文件的
using namespace std;//命名空间,防止重名给程序带来各种隐患,使用cin,cout,stack,map,set,vector,queue时都要使用
int main()
{
string s;//定义一个字符串
s.push_back('1');//往栈里放入一个元素1
s.push_back('2');//往栈里放入一个元素2
s.push_back('3'); //往栈里放入一个元素3
cout<<"按顺序放入字符1、2、3后,目前string里的元素:" ;
for(int i=0;i<s.size();i++){
cout<<s[i]<<' ';
}
cout<<endl;
cout<<"s.pop_back()="<<s.size()<<endl;//s.size()返回string内字符的个数
cout<<"s.empty()="<<s.empty()<<endl; //判断栈是否为空,值为1代表空,0代表非空,用s.size()同样可以判断 ,s.size()的值为0就代表空的
cout<<"s.back()="<<s.back()<<endl;//查看栈顶的元素
cout<<endl;
s.pop_back();//弹出栈顶元素
cout<<"s.pop_back()后,目前string里的元素:";
for(int i=0;i<s.size();i++){//可以通过下标随机访问元素
cout<<s[i]<<' ';
}
cout<<endl;
cout<<"s.size()="<<s.size()<<endl;
cout<<"s.empty()="<<s.empty()<<endl;
cout<<"s.back()="<<s.back()<<endl;
cout<<endl;
s.pop_back();
cout<<"s.pop_back()后,目前string里的元素:";
for(int i=0;i<s.size();i++){
cout<<s[i]<<' ';
}
cout<<endl;
cout<<"s.size()="<<s.size()<<endl;
cout<<"s.empty()="<<s.empty()<<endl;
cout<<"s.back()="<<s.back()<<endl;
cout<<endl;
s.pop_back();
cout<<"s.pop_back()后,目前的string是空的"<<endl;
cout<<"s.size()="<<s.size()<<endl;
cout<<"string是空的就不能用s.back()访问栈顶元素了" <<endl;
cout<<"s.empty()="<<s.empty()<<endl;
return 0;
}
运行结果:
按顺序放入字符1、2、3后,目前string里的元素:1 2 3
s.pop_back()=3
s.empty()=0
s.back()=3
s.pop_back()后,目前string里的元素:1 2
s.size()=2
s.empty()=0
s.back()=2
s.pop_back()后,目前string里的元素:1
s.size()=1
s.empty()=0
s.back()=1
s.pop_back()后,目前的string是空的
s.size()=0
string是空的就不能用s.back()访问栈顶元素了
s.empty()=1
2.3 从stack到vector
vector的栈相关的成员函数
empty() //堆栈为空则返回真
pop_back() //移除栈顶元素
push_back() //在栈顶增加元素
size() //返回栈中元素数目
back() //返回栈顶元素
#include<iostream>//c++标准头文件,可以使用cout,cin等标准库函数
#include<vector>//使用vector时需要的头文件
using namespace std;//命名空间,防止重名给程序带来各种隐患,使用cin,cout,stack,map,set,vector,queue时都要使用
int main(){
vector<int> v;//定义一个int类型的stack
v.push_back(1);//往vector里放入一个元素1
v.push_back(2);//往vector里放入一个元素2
v.push_back(3); //往vector里放入一个元素3
cout<<"按顺序放入字符1、2、3后,目前vector里的元素:" ;
for(int i=0;i<v.size();i++){//可以通过下标随机访问元素
cout<<v[i]<<' ';
}
cout<<endl;
cout<<"v.pop_back()="<<v.size()<<endl;//v.size()返回vector内元素的个数
cout<<"v.empty()="<<v.empty()<<endl; //判断栈是否为空,值为1代表空,0代表非空,用v.size()同样可以判断 ,v.size()的值为0就代表空的
cout<<"v.back()="<<v.back()<<endl;//查看栈顶的元素
cout<<endl;
v.pop_back();//弹出栈顶元素
cout<<"v.pop_back()后,目前vector里的元素:";
for(int i=0;i<v.size();i++){
cout<<v[i]<<' ';
}
cout<<endl;
cout<<"v.size()="<<v.size()<<endl;
cout<<"v.empty()="<<v.empty()<<endl;
cout<<"v.back()="<<v.back()<<endl;
cout<<endl;
v.pop_back();
cout<<"v.pop_back()后,目前vector里的元素:";
for(int i=0;i<v.size();i++){
cout<<v[i]<<' ';
}
cout<<endl;
cout<<"v.size()="<<v.size()<<endl;
cout<<"v.empty()="<<v.empty()<<endl;
cout<<"v.back()="<<v.back()<<endl;
cout<<endl;
v.pop_back();
cout<<"v.pop_back()后,目前的vector是空的"<<endl;
cout<<"v.size()="<<v.size()<<endl;
cout<<"vtring是空的就不能用v.back()访问栈顶元素了" <<endl;
cout<<"v.empty()="<<v.empty()<<endl;
return 0;
}
运行结果:
按顺序放入字符1、2、3后,目前vector里的元素:1 2 3
v.pop_back()=3
v.empty()=0
v.back()=3
v.pop_back()后,目前vector里的元素:1 2
v.size()=2
v.empty()=0
v.back()=2
v.pop_back()后,目前vector里的元素:1
v.size()=1
v.empty()=0
v.back()=1
v.pop_back()后,目前的vector是空的
v.size()=0
vtring是空的就不能用v.back()访问栈顶元素了
v.empty()=1
3 C++中queue用法
queue:先进先出
包含头文件:#include <queue>
queue的定义 :
queue<int> q1;
queue<double> q2;
queue<string> q3;
queue<结构体类型> q4;
基本使用方法:
back() // 返回队列中最后一个元素
empty() // 判断队列是否为空
front() // 返回队列中的第一个元素
pop() // 删除队列的第一个元素
push() // 在队列末尾加入一个元素
size() // 返回队列中元素的个数
#include <iostream>
#include <queue>
using namespace std;
int main()
{
queue<int> q;
q.push(1);
q.push(2);
q.push(3);
q.push(4);
while (!q.empty()) {
cout << q.front() << " ";
q.pop();
}
}
运行结果:
1 2 3 4
4 C++中list用法
4.1 list构造
list<int> lt1; // 构造int类型的空容器
list<int> lt2(3, 2); // 构造含有3个2的int类型容器
list<int> lt3(lt2); // 拷贝构造lt2
string s("hello");
list<char> lt4(s.begin(), s.end()); // 利用迭代器构造
4.2 list插入和删除数据
push_front和pop_front
#include <iostream>
#include <list>
using namespace std;
int main()
{
list<int> lt;
// 头插数据
lt.push_front(1);
lt.push_front(2);
lt.push_front(3);
for (auto e : lt)
{
cout << e << " ";
}
cout << endl;
// 头删数据
lt.pop_front();
for (auto e : lt)
{
cout << e << " ";
}
cout << endl;
return 0;
}
运行结果
3 2 1
2 1
push_back和pop_back
#include <iostream>
#include <list>
using namespace std;
int main()
{
list<int> lt;
// 尾插数据
lt.push_back(1);
lt.push_back(2);
lt.push_back(3);
for (auto e : lt)
{
cout << e << " ";
}
cout << endl;
// 尾删数据
lt.pop_back();
for (auto e : lt)
{
cout << e << " ";
}
cout << endl;
return 0;
}
运行结果:
1 2 3
1 2
insert
支持三种插入方式:
- 在指定位置插入数据
- 在指定位置插入n个值为val的数
- 在指定位置插入一段迭代器区间(左闭右开)
int main()
{
list<int> lt;
lt.push_back(1);
lt.push_back(2);
lt.push_back(3);
list<int>::iterator pos = find(lt.begin(), lt.end(), 2);
lt.insert(pos, 4); //在2的位置插入4
for (auto e : lt)
{
cout << e << " ";
}
cout << endl;
pos = find(lt.begin(), lt.end(), 3);
lt.insert(pos, 3, 5); //在3的位置插入3个5
for (auto e : lt)
{
cout << e << " ";
}
cout << endl;
vector<int> v{ 6, 6 };
pos = find(lt.begin(), lt.end(), 1);
lt.insert(pos, v.begin(), v.end()); //在1的位置插入2个6
for (auto e : lt)
{
cout << e << " ";
}
cout << endl;
return 0;
}
运行结果:
1 4 2 3
1 4 2 5 5 5 3
6 6 1 4 2 5 5 5 3
erase
有两种删除方式:
- 删除指定位置数据
- 删除指定迭代器区间中的数据
int main()
{
list<int> lt;
lt.push_back(1);
lt.push_back(2);
lt.push_back(3);
lt.push_back(4);
list<int>::iterator pos = find(lt.begin(), lt.end(), 2);
lt.erase(pos); // 删除2
for (auto e : lt)
{
cout << e << " ";
}
cout << endl;
pos = find(lt.begin(), lt.end(), 3);
lt.erase(pos, lt.end()); //删除3及其之后的元素
for (auto e : lt)
{
cout << e << " ";
}
cout << endl;
return 0;
}
运行结果:
1 3 4
1
4.3 list迭代器的使用
#include <iostream>
#include <list>
using namespace std;
int main()
{
string s("hello");
list<char> lt(s.begin(), s.end());
//正向迭代器遍历容器
list<char>::iterator it = lt.begin();
while (it != lt.end())
{
cout << *it << " ";
it++;
}
cout << endl;
//反向迭代器遍历容器
list<char>::reverse_iterator rit = lt.rbegin();
while (rit != lt.rend())
{
cout << *rit << " ";
rit++;
}
cout << endl;
return 0;
}
运行结果:
h e l l o
o l l e h
4.4 基本操作
front和back
#include <iostream>
#include <list>
using namespace std;
int main()
{
list<int> lt;
lt.push_back(1);
lt.push_back(2);
lt.push_back(3);
lt.push_back(4);
cout << lt.front() << endl;
cout << lt.back() << endl;
return 0;
}
运行结果:
1
4
empty和size
#include <iostream>
#include <list>
using namespace std;
int main()
{
list<int> lt;
lt.push_back(1);
lt.push_back(2);
cout << lt.size() << endl;
cout << lt.empty() << endl;
}
运行结果:
2
0
4.5 list相关操作函数
swap
:用于交换两个容器的内容
#include <iostream>
#include <list>
using namespace std;
int main()
{
list<int> lt1(3, 2);
list<int> lt2(2, 3);
lt1.swap(lt2); // 交换两个容器的内容
for (auto a : lt1) {
cout << a << " ";
}
return 0;
}
运行结果:
3 3
clear
:用于清空容器,清空后容器的size为0
#include <iostream>
#include <list>
using namespace std;
int main()
{
list<int> lt(3, 2);
lt.clear();
cout << lt.size() << endl;
return 0;
}
运行结果:
0
sort
:将容器当中的数据排序(升序)
#include <iostream>
#include <list>
using namespace std;
int main()
{
list<int> lt;
lt.push_back(2);
lt.push_back(1);
lt.push_back(4);
lt.push_back(3);
for (auto e : lt)
{
cout << e << " ";
}
cout << endl;
lt.sort();
for (auto e : lt)
{
cout << e << " ";
}
cout << endl;
}
运行结果:
2 1 4 3
1 2 3 4
resize
操作方式有两种:
#include <iostream>
#include <list>
using namespace std;
int main()
{
list<int> lt(3, 3);
for (auto e : lt)
{
cout << e << " ";
}
cout << endl;
lt.resize(5, 4); //将size扩大为5,扩大的值为4
for (auto e : lt)
{
cout << e << " ";
}
cout << endl;
lt.resize(2); //将size缩小为2
for (auto e : lt)
{
cout << e << " ";
}
cout << endl;
return 0;
}
运行结果:
3 3 3
3 3 3 4 4
3 3
remove
:移除指定元素
int main()
{
list<int> lt;
lt.push_back(1);
lt.push_back(2);
lt.push_back(2);
lt.push_back(3);
for (auto e : lt)
{
cout << e << " ";
}
cout << endl;
lt.remove(2); // 删除容器当中值为2的元素
for (auto e : lt)
{
cout << e << " ";
}
cout << endl;
return 0;
}
运行结果:
1 2 2 3
1 3
unique
:去除连续重复的元素(如果要去除所有重复的元素需要先排序)
#include <iostream>
#include <list>
using namespace std;
int main()
{
list<int> lt;
lt.push_back(1);
lt.push_back(2);
lt.push_back(3);
lt.push_back(3);
lt.push_back(2);
lt.push_back(3);
lt.push_back(2);
for (auto e : lt)
{
cout << e << " ";
}
cout << endl;
lt.unique();// 去除连续重复的元素
for (auto e : lt)
{
cout << e << " ";
}
cout << endl;
lt.sort();// 排序
lt.unique();
for (auto e : lt)
{
cout << e << " ";
}
cout << endl;
return 0;
}
运行结果:
1 2 3 3 2 3 2
1 2 3 2 3 2
1 2 3
reverse
:将容器当中元素的进行逆置
#include <iostream>
#include <list>
using namespace std;
int main()
{
list<int> lt;
lt.push_back(1);
lt.push_back(2);
lt.push_back(3);
for (auto e : lt)
{
cout << e << " ";
}
cout << endl;
lt.reverse();// 逆置
for (auto e : lt)
{
cout << e << " ";
}
cout << endl;
return 0;
}
运行结果:
1 2 3
3 2 1
5 C++中pair用法
pair
:将2个数据整合成一组数据,本质其实就是个结构体,它含有两个成员变量first和second。
包含头文件:#include <utility>
template<class T1,class T2> struct pair
#include<utility>
#include<iostream>
using namespace std;
int main()
{
pair<string, string>s1;
s1.first="ctx";
s1.second="666";
cout<<s1.first<<endl;
cout<<s1.second<<endl;
cout<<s1.first<<s1.second<<endl;
}
定义
pair<int, int> p1;
pair<int, double> p2;
pair<double, string> p3;
pair<string, vector<int>> p4;
初始化赋值
pair<string, string> p1("a", "b");
pair<string, int> p2("a", 23);
pair<string, int> p3(p2); // 拷贝p2的值来初始化p3
pair<string, int> p3 = p2; // 将p2的值赋值给p3
typedef简化pair的定义
typedef pair<int, int> intInt;
intInt c1(1, 2);
pair中的make_pair
:一般make_pair都使用在需要pair做参数的位置,可以直接调用make_pair生成pair对象。 另一个使用的方面就是pair可以接受隐式的类型转换,这样可以获得更高的灵活度。
pair<int, double> p1;
p1 = make_pair(1, 1.2);
// 第一个的second变量是float类型
// 而make_pair函数会将second变量都转换成double类型。
std::pair<int, float>(18, 1.78);
std::make_pair(18, 1.78);
6 C++中map用法
map是STL的一个关联容器,以键值对存储的数据,map内部有序(自动排序,单词时按照字母序排序),查找时间复杂度为O(logn)。
包含头文件:#include <map>
定义
map<string, int> my_map;
typedef map<string,int> My_Map;
My_Map my_map;
6.1 基本方法
- my_map.insert()或按照数组直接赋值:插入
- my_map.find():查找一个元素
- my_map.clear():清空
- my_map.erase():删除一个元素
- my_map.size():map的长度大小
- my_map.begin():返回指向map头部的迭代器
- my_map.end():返回指向map末尾的迭代器
- my_map.rbegin():返回一个指向map尾部的逆向迭代器
- my_map.rend():返回一个指向map头部的逆向迭代器
- my_map.empty():map为空时返回true
- swap():交换两个map,两个map中所有元素都交换
6.2 map插入数据的几种方法
用insert函数插入pair数据:
map<int, string> my_map;
my_map.insert(pair<int, string>(1, "a"));
用insert函数插入value_type数据:
map<int,string> my_map;
my_map.insert(map<int,string>::value_type(1,"first"));
my_map.insert(map<int,string>::value_type(2,"second"));
map<int,string>::iterator it; //迭代器遍历
for(it=my_map.begin();it!=my_map.end();it++)
cout<<it->first<<it->second<<endl;
用数组的方式直接赋值:
map<int, string> my_map;
my_map[1] = "first";
6.3 查找元素(判定这个关键字是否在map中出现)
用count函数来判断关键字是否出现,其缺点是无法定位元素出现的位置。由于map一对一的映射关系,count函数的返回值要么是0,要么是1
map<string, int> my_map;
my_map["first"] = 1;
cout << my_map.count("first") << endl;
用find函数来定位元素出现的位置,它返回一个迭代器,当数据出现时,返回的是数据所在位置的迭代器;若map中没有要查找的数据,返回的迭代器等于end函数返回的迭代器。
#include <map>
#include <string>
#include <iostream>
using namespace std;
int main()
{
map<int, string> my_map;
my_map.insert(pair<int, string>(1, "student_one"));
my_map.insert(pair<int, string>(2, "student_two"));
my_map.insert(pair<int, string>(3, "student_three"));
map<int, string>::iterator it;
it = my_map.find(1);
if(it != my_map.end())
cout<<"Find, the value is "<<it->second<<endl;
else
cout<<"Do not Find"<<endl;
return 0;
}
//通过map对象的方法获取的iterator数据类型是一个std::pair对象,包括两个数据iterator->first和iterator->second,分别代表关键字和value值。
6.4 删除元素
#include <map>
#include <string>
#include <iostream>
using namespace std;
int main()
{
map<int, string> my_map;
my_map.insert(pair<int, string>(1, "one"));
my_map.insert(pair<int, string>(2, "two"));
my_map.insert(pair<int, string>(3, "three"));
//如果你要演示输出效果,请选择以下的一种,你看到的效果会比较好
//如果要删除1,用迭代器删除
map<int, string>::iterator it;
it = my_map.find(1);
my_map.erase(it); //如果要删除1,用关键字删除
int n = my_map.erase(1); //如果删除了会返回1,否则返回0
//用迭代器,成片的删除
//一下代码把整个map清空
my_map.erase( my_map.begin(), my_map.end() );
//成片删除要注意的是,也是STL的特性,删除区间是一个前闭后开的集合
//自个加上遍历代码,打印输出吧
return 0;
}
6.5 排序,按value排序
map中元素是自动按key升序排序(从小到大)的;按照value排序时,想直接使用sort函数是做不到的,sort函数只支持数组、vector、list、queue
等的排序,无法对map排序,那么就需要把map放在vector中,再对vector进行排序。
#include <iostream>
#include <string>
#include <map>
#include <algorithm>
#include <vector>
using namespace std;
bool cmp(pair<string,int> a, pair<string,int> b) {
return a.second < b.second;
}
int main()
{
map<string, int> ma;
ma["Alice"] = 86;
ma["Bob"] = 78;
ma["Zip"] = 92;
ma["Stdevn"] = 88;
vector< pair<string,int> > vec(ma.begin(),ma.end());
//或者:
//vector< pair<string,int> > vec;
//for(map<string,int>::iterator it = ma.begin(); it != ma.end(); it++)
// vec.push_back( pair<string,int>(it->first,it->second) );
sort(vec.begin(),vec.end(),cmp);
for (vector<pair<string,int>>::iterator it = vec.begin(); it != vec.end(); ++it)
{
cout << it->first << " " << it->second << endl;
}
return 0;
}
7 C++中unordered_map用法
包含头文件:#include <unordered_map>
map和unordered_map各自优缺点
- map
- unordered_map
定义
unordered_map<string, string> umap;
初始化
unordered_map<string, string> umap{
{"as", "as"},
{"s", "ass"},
{"v", "qwe"}
};
调用 unordered_map 模板中提供的复制(拷贝)构造函数,将现有 unordered_map 容器中存储的键值对,复制给新建 unordered_map 容器
unordered_map<string, string> umap2(umap);
包含 umap 容器中除第 1 个键值对外的所有其它键值对
unordered_map<string, string> umap2(++umap.begin(), umap.end());
#include<iostream>
#include<unordered_map>
#include<map>
#include<string>
using namespace std;
int main()
{
// 注意:c++11才开始支持括号初始化
unordered_map<int, string> myMap = {{5, "zhangsan"},{6, "lisi"}}; // 使用{}赋值
myMap[2] = "wanger"; // 使用[ ] 进行当个插入,若已存在键值2,则赋值修改,若无则插之。
myMap.insert(pair<int, string>(3, "mazi")); // 使用insert和pair插入。
// 遍历输出+迭代器的使用。
auto iter = myMap.begin(); // auto自动识别为迭代器类型unordered_map<int, string>::iterator
while(iter != myMap.end())
{
cout << iter->first << "," << iter->second << endl;
++iter;
}
// 查找元素并输出 + 迭代器的使用
auto iterator = myMap.find(6); // find()返回一个指向2的迭代器。
if(iterator != myMap.end())
cout << endl << iterator->first << "," << iterator->second << endl;
system("pause");
return 0;
}
运行结果:
3,mazi
2,wanger
6,lisi
5,zhangsan
6,lisi
c++ unordered_map容器的成员方法
8 C++中set用法
set是一个有序的容器,里面的元素都是排序好的,支持插入,删除,查找等操作,就像一个集合一样。所有的操作的都是严格在logn时间之内完成,效率非常高。set 和 multiset 的区别是:set 插入的元素不能相同,但是 multiset 可以相同。
set特点
:
- 每个元素的键值都唯一,不允许两个元素有相同的键值
- 所有元素都会根据元素的键值自动排序(默认从小到大)
- set 中的元素不像 map 那样可以同时拥有实值(value)和键值(key),只能存储键,是单纯的键的集合
- set 中元素的值不能直接被改变
- set 支持大部分的map的操作,但是 set 不支持下标的操作,而且没有定义mapped_type类型
包含头文件:#include <set>
8.1 set 的基本操作
set 的定义及初始化
set<Type> s // 定义一个set容器
set<Type> s(s1) // 定义一个set容器,并用容器s1来初始化
set<Type> s(b, e) // b和e分别为迭代器的开始和结束的标记
set<Type> s(s1.begin(), s1.begin()+3) // 用容器s1的第0个到第2个值初始化s
set<Type> s(a, a + 5) // 将a数组的元素初始化vec向量,不包括a[4]
set<Type> s(&a[1], &a[4]) // 将a[1]~a[4]范围内的元素作为s的初始值
set 的基本操作
s.begin() // 返回指向第一个元素的迭代器
s.end() // 返回指向最后一个元素的迭代器
s.clear() // 清除所有元素
s.count() // 返回某个值元素的个数
s.empty() // 如果集合为空,返回true,否则返回false
s.equal_range() // 返回集合中与给定值相等的上下限的两个迭代器
s.erase() // 删除集合中的元素
s.find(k) // 返回一个指向被查找到元素的迭代器
s.insert() // 在集合中插入元素
s.lower_bound(k) // 返回一个迭代器,指向键值大于等于k的第一个元素
s.upper_bound(k) // 返回一个迭代器,指向键值大于k的第一个元素
s.max_size() // 返回集合能容纳的元素的最大限值
s.rbegin() // 返回指向集合中最后一个元素的反向迭代器
s.rend() // 返回指向集合中第一个元素的反向迭代器
s.size() // 集合中元素的数目
8.2 set 的用法
#include <iostream>
#include <set>
using namespace std;
int main(){
set<int> s;
s.insert(1);
s.insert(2);
s.insert(3);
s.insert(1);
cout<<"set的size值为 :"<<s.size()<<endl;
cout<<"set的maxsize的值为 :"<<s.max_size()<<endl;
cout<<"set中的第一个元素是 :"<<*s.begin()<<endl;
cout<<"set中的最后一个元素是:"<<*s.end()<<endl;
s.clear();
if(s.empty())
cout<<"set为空"<<endl;
cout<<"set的size值为 :"<<s.size()<<endl;
cout<<"set的maxsize的值为 :"<<s.max_size()<<endl;
return 0;
}
count() 的用法
//返回某个值元素的个数
#include <iostream>
#include <set>
using namespace std;
int main(){
set<int> s;
s.insert(1);
s.insert(2);
s.insert(3);
s.insert(1);
cout<<"set 中 1 出现的次数是 :"<<s.count(1)<<endl;
cout<<"set 中 4 出现的次数是 :"<<s.count(4)<<endl;
return 0;
}
erase() 的用法
#include <iostream>
#include <set>
using namespace std;
int main(){
set<int> s;
set<int>::const_iterator it;
set<int>::iterator first;
set<int>::iterator second;
for(int i=1; i<=10; ++i)
s.insert(i);
//第一种删除,删掉1
s.erase(s.begin());
//第二种删除,删掉2和3
first = s.begin();
second = s.begin();
second++;
second++;
s.erase(first,second);
//第三种删除,删掉8
s.erase(8);
cout<<"删除后 set 中元素是 :";
for(it=s.begin(); it!=s.end(); ++it)
cout<<*it<<" ";
cout<<endl;
return 0;
}
find() 的用法
//返回一个指向被查找到元素的迭代器,如果没找到则返回end()
#include <iostream>
#include <set>
using namespace std;
int main(){
int a[] = {4,5,6};
set<int> s(a,a+3);
set<int>::iterator it;
if((it=s.find(4))!=s.end())
cout<<*it<<endl;
return 0;
}
insert() 的用法
#include <iostream>
#include <set>
using namespace std;
int main(){
int a[] = {1,2,3};
set<int> s;
set<int>::iterator it;
s.insert(a,a+3);
for(it=s.begin(); it!=s.end(); ++it)
cout<<*it<<" ";
cout<<endl;
pair<set<int>::iterator,bool> pr;
pr=s.insert(5);
if(pr.second)
cout<<*pr.first<<endl;
cout<<"插入数值之后的set中有:"<<endl;
for(it=s.begin(); it!=s.end(); ++it)
cout<<*it<<" ";
cout<<endl;
return 0;
}
lower_bound()、upper_bound() 的用法
#include <iostream>
#include <set>
using namespace std;
int main(){
set<int> s;
s.insert(1);
s.insert(3);
s.insert(4);
s.insert(6);
cout<<*s.lower_bound(1)<<endl; // 1
cout<<*s.lower_bound(2)<<endl; // 3
cout<<*s.upper_bound(3)<<endl; // 4
return 0;
}
equal_range() 的用法
#include <iostream>
#include <set>
#include <algorithm>
using namespace std;
int main(){
set<int> s;
set<int>::iterator it;
for(int i=1; i<=5; ++i)
s.insert(i); //向set中加入数据
for(it=s.begin(); it!=s.end(); ++it)
cout<<*it<<" "; //输出set中的数据
cout<<endl;
pair<set<int>::const_iterator,set<int>::const_iterator> pr;
pr=s.equal_range(3);
cout<<"第一个大于等于3的数是:"<<*pr.first<<endl;
cout<<"第一个大于3的数是: "<<*pr.second<<endl;
return 0;
}
运行结果:
1 2 3 4 5
第一个大于等于3的数是:3
第一个大于3的数是:4
自定义比较函数
- 元素不是结构体
//自定义比较函数myComp,重载“()”操作符
struct myComp{
bool operator()(const your_type &a,const your_type &b){
return a.data > b.data;
}
}
set<int,myComp>s;
set<int,myComp>::iterator it;
- 元素是结构体
//可以直接将比较函数写在结构体内
struct Info{
string name;
float score;
//重载“<”操作符,自定义排序规则
bool operator < (const Info &a) const{
//按score从大到小排列
return a.score<score;
}
}
set<Info> s;
set<Info>::iterator it;
9 C++中unordered_set用法
包含头文件:#include <unordered_set>
9.1 unordered_set的初始化
创建空的set
unordered_set<int> set1;
拷贝构造
unordered_set<int> set2(set1);
使用迭代器构造
unordered_set<int> set3(set1.begin(), set1.end());
使用数组作为其初值进行构造
unordered_set<int> set4(arr,arr+5);
移动构造
unordered_set<int> set5(move(set2));
使用处置列表进行构造
unordered_set<int> set6 {1,2,10,10};
9.2 unordered_set的常用内置函数
empty()函数——判断是否为空
set1.empty();
find()函数——查找:找到返回迭代器,失败返回end()
set1.find(2);
count()函数——出现次数
set1.count(2);
insert()函数——插入元素
//插入元素,返回pair<unordered_set<int>::iterator, bool>
set1.insert(3);
//使用initializer_list插入元素
set1.insert({1,2,3});
//指定插入位置,如果位置正确会减少插入时间,返回指向插入元素的迭代器
set1.insert(set1.end(), 4);
//使用范围迭代器插入
set1.insert(set2.begin(), set2.end());
9.3 关于insert函数的返回值
insert()只传入单个参数(待插入元素)
- 会返回一个 pair 对象
- 这个 pair 对象包含一个迭代器,以及一个附加的布尔值用来说明插入是否成功
- 如果元素被插入,返回的迭代器会指向新元素
- 如果没有被插入,迭代器指向阻止插入的元素
auto pr = words.insert("ninety"); // Returns a pair - an iterator & a bool value
insert()传入两个参数(迭代器+待插入元素)
- 可以用一个迭代器作为insert()的第一个参数,它指定了元素被插入的位置
- 在这种情况下,只会返回一个迭代器
auto iter = words.insert (pr.first, "nine"); // 1st arg is a hint. Returns an iterator
insert()传入初始化列表
- 插入初始化表中的元素
- 在这种情况下,什么都没有返回
words.insert({"ten", "seven", "six"}); // Inserting an initializer list
emplace()函数——插入元素(转移构造)
//使用转移构造函数添加新元素3,比insert效率高
set1.emplace(3);
erase()函数——删除元素
//删除操作,成功返回1,失败返回0
set1.erase(1);
//删除操作,成功返回下一个pair的迭代器
set1.erase(set1.find(1));
//删除set1的所有元素,返回指向end的迭代器
set1.erase(set1.begin(), set1.end());
bucket_count()函数——篮子数目
//返回容器中的篮子总数
set1.bucket_count();
bucket_size()函数——篮子中元素数目
//返回1号篮子中的元素数
set1.bucket_size(1);
bucket()函数——在哪个篮子
//元素1在哪一个篮子
set1.bucket(1);
clear()函数——清空
set1.clear();
load_factor()函数——负载因子
//负载因子,返回每个篮子元素的平均数,即size/float(bucket_count);
set1.load_factor();
rehash()函数——设置篮子数目并重新分布
//设置篮子的数量为20,并且重新rehash
set1.rehash(20);
本文详解了STL中的vector、stack、queue、list、pair、map、unordered_map、set、unordered_set,不正之处望读者指教。