你不知道的C++ STL库

STL 提供三种类型的组件:容器、迭代器和算法,它们都支持泛型程序设计标准。
容器主要有两类:顺序容器和关联容器。
顺序容器(vector、 list、 deque 和 string等)是一系列元素的有序集合。
关联容器(set、 multiset、 map 和 multimap)包含查找元素的键值。
迭代器的作用是遍历容器。
STL 算法库包含四类算法:排序算法、不可变序算法、变序性算法和数值算法。

文章目录

1.vector 向量容器

vector 向量容器不但能像数组一样对元素进行随机访问,还能在尾部插入元素,是一
种简单、高效的容器,完全可以代替数组。
vector 具有内存自动管理的功能,对于元素的插入和删除,可动态调整所占的内存空间。
vector 容器的下标是从 0 开始计数的,也就是说,如果 vector 容器的大小是 n,那么,元素的下标是 0~n-1。对于 vector 容器的容量定义,可以事先定义一个固定大小,事后,可以随时调整其大小;也可以事先不定义,随时使用 push_back()方法从尾部扩张元素,也可以使用 insert()在某个元素位置前插入新元素。
vector 容器有两个重要的方法, begin()和 end()。 begin()返回的是首元素位置的迭代器;end()返回的是最后一个元素的下一元素位置的迭代器。

#include <vector>
using namespace std;

###1.1创建 vector 对象
创建 vector 对象常用的有三种形式。
(1)不指定容器的元素个数,如定义一个用来存储整型的容器:

vector<int> v;

(2)创建时,指定容器的大小,如定义一个用来存储 10 个 double 类型元素的向量容器:

vector<double> v(10);

注意,元素的下标为 0~9;另外,每个元素的值被初始化为 0.0。
(3)创建一个具有 n 个元素的向量容器对象,每个元素具有指定的初始值:

vector<double> v(108.6);

上述语句定义了 v 向量容器,共有 10 个元素,每个元素的值是 8.6。
###1.2尾部元素扩张
通常使用 push_back()对 vector 容器在尾部追加新元素。尾部追加元素, vector 容器会自动分配新内存空间。可对空的 vector 对象扩张,也可对已有元素的 vector 对象扩张。

vector<int> v;
v.push_back(33);

###1.3下标方式访问 vector 元素
访问或遍历 vector 对象是常要做的事情。对于 vector 对象,可以采用下标方式随意访
问它的某个元素,当然,也可以以下标方式对某元素重新赋值,这点类似于数组的访问方式。

vector<int> v(2);
v[0]=2;
v[1]=7;

###1.4用迭代器访问 vector 元素
常使用迭代器配合循环语句来对 vector 对象进行遍历访问,迭代器的类型一定要与它
要遍历的 vector 对象的元素类型一致。

vector<int>::iterator it;
for(it=v.begin();it!=v.end();it++)
{
//输出迭代器上的元素值
cout<<*it<<" ";
}

###1.5元素的插入
insert()方法可以在 vector 对象的任意位置前插入一个新的元素,同时, vector 自动扩
张一个元素空间,插入位置后的所有元素依次向后挪动一个位置。
要注意的是, insert()方法要求插入的位置,是元素的迭代器位置,而不是元素的下标。

//在最前面插入新元素,元素值为 8
v.insert(v.begin(),8);
//在第 2 个元素前插入新元素 1
v.insert(v.begin()+2,1);
//在向量末尾追加新元素 3
v.insert(v.end(),3);

###1.6元素的删除
erase()方法可以删除 vector 中迭代器所指的一个元素或一段区间中的所有元素。
clear()方法则一次性删除 vector 中的所有元素。

//删除 2 个元素,从 0 开始计数
v.erase(v.begin()+2);
//清空向量
v.clear();

###1.7使用 reverse 反向排列算法
reverse 反向排列算法,需要定义头文件**“#include <algorithm>”, algorithm 文件位于C:\Program Files\Microsoft Visual Studio\VC98\Include** 文件夹中。
reverse 算法可将向量中某段迭代器区间元素反向排列.

//反向排列向量的从首到尾间的元素
reverse(v.begin(),v.end());

###1.8使用 sort 算法对向量元素排序
使用 sort 算法,需要声明头文件**“#include <algorithm>”**。
sort 算法要求使用随机访问迭代器进行排序,在默认的情况下,对向量元素进行升序
排列

//排序,升序排列
sort(v.begin(),v.end());


//自己设计排序比较函数:对元素的值进行降序排列
bool Comp(const int &a,const int &b)
{
if(a!=b)return a>b;
else return a>b;
}
//按 Comp 函数比较规则排序
sort(v.begin(),v.end(),Comp);

###1.9向量的大小
使用 size()方法可以返回向量的大小,即元素的个数。
使用 empty()方法返回向量是否为空。

//向量的大小
v.size();
//向量是否为空,如果非空,则返回逻辑假,即 0,否则返回逻辑真,即 1
v.empty();

##2.string 基本字符系列容器
C++STL 提供了 string 基本字符系列容器来处理字符串, 可以把 string理解为字符串类,它提供了添加、删除、替换、查找和比较等丰富的方法。
使用 string 容器,需要头文件包含声明**“#include <string>”**。 string 文件在 C:\ProgramFiles\Microsoft Visual Studio\VC98\Include 文件夹中可以找到。
###2.1创建 string 对象
创建了字符串对象 s, s 是一个空字符串,其长度为 0:

string s;
s.length();

###2.2给 string 对象赋值
给 string 对象赋值一般有两种方式。
(1)直接给字符串对象赋值

string s;
s="hello,C++STL.";

(2)更常用的方法是,把字符指针赋给一个字符串对象

string s;
char ss[5000];
//scanf 的输入速度比 cin 快得多
//scanf 是 C 语言的函数,不支持 string 对象
scanf("%s",&ss);
//把整个字符数组赋值给 string 对象
s=ss;

###2.3从 string 对象尾部添加字符
在 string 对象的尾部添加一个字符(char),采用“+”操作符即可.

string s;
s=s+'a';
s=s+'b';
s=s+'c';
//s="abc";

###2.4从 string 对象尾部追加字符串
从尾部追加的方式有两种。
(1)直接采用“+”操作符

string s;
s=s+"abc";
s=s+"123";
//s="abc123"

(2)采用 append()方法

string s;
s.append("abc");
s.append("123");
//s="abc123"

###2.5给 string 对象插入字符
可以使用 insert()方法把一个字符插入到迭代器位置之前

string s;
s="123456";
//定义迭代器
string::iterator it;
//迭代器位置为字符串首
it=s.begin();
//把字符'p'插入到第 1 个字符前(注意,字符位置是从 0 开始计数)
s.insert(it+1,'p');
//s=1p23456

###2.6访问 string 对象的元素
一般使用下标方式随机访问 string 对象的元素,下标是从 0 开始计数的。另外, string
对象的元素是一个字符(char)

string s;
s="abc123456";
//输出 string 对象的首元素a
cout<<s[0]<<endl;
//两个相同的字符相减值为 0
cout<<s[0]-'a'<<endl;

###2.7删除 string 对象的元素
(1)清空一个字符串,则直接给它赋空字符串即可。
(2)使用 erase()方法删除迭代器所指的那个元素或一个区间中的所有元素。

string s;
s="abc123456";
//定义迭代器变量,指向字符串对象首元素
string::iterator it=s.begin();
//删除第 3 个元素,元素位置从 0 开始计数
s.erase(it+3);
//删除 0~4 区间的所有元素
s.erase(it,it+4);
//清空字符串
s="";

###2.8返回 string 对象的长度
采用 length()方法可返回字符串的长度;采用 empty()方法,可返回字符串是否为空,
如果字符串为空,则返回逻辑真,即 1,否则,返回逻辑假,即 0。

//字符串长度
s.length();
//判断字符串是否为空
s.empty();

###2.9替换 string 对象的字符
使用 replace()方法可以很方便地替换 string 对象中的字符, replace()方法的重载函数相
当多,常用的只有一两个

string s;
s="abc123456";
//从第 3 个开始,将连续的 3 个字符替换为“good”
//即将“abc”替换为“good”
s.replace(3,3,"good");
//s=abcgood456

###2.10搜索 string 对象的元素或子串
采用 find()方法可查找字符串中的第一个字符元素(char, 用单引号界定)或者子串(用双引号界定), 如果查到, 则返回下标值(从 0 开始计数), 如果查不到, 则返回 4294967295。

string s;
s="cat dog cat";
//查找第一个字符‘c’,返回下标值
cout<<s.find('c')<<endl;
//查找第一个子串“dog”,返回下标值
cout<<s.find("dog")<<endl;
//查找第一个子串“dogc”,查不到则返回 4294967295
cout<<s.find("dogc")<<endl;

###2.11string 对象的比较
string 对象可与使用 compare()方法与其他字符串相比较。如果它比对方大,则返回 1;如果它比对方小,则返回-1;如果它与对方相同(相等),则返回 0。

string s;
s="cat dog cat";
//s 比“cat”字符串大,返回 1
cout<<s.compare("cat")<<endl;
//s 与“cat dog cat”相等,返回 0
cout<<s.compare("cat dog cat")<<endl;
//s 比“dog”小,返回-1
cout<<s.compare("dog")<<endl;

###2.12用 reverse 反向排序 string 对象
采用 reverse()方法可将 string 对象迭代器所指向的一段区间中的元素(字符)反向排
序。 reverse()方法需要声明头文件**“#include <algorithm>”**。

string s;
s="123456789";
reverse(s.begin(),s.end());
//s=987654321

###2.13string 对象作为 vector 元素
string 对象可以作为 vector 向量的元素,这种用法,类似于字符串数组。

vector<string> v;
v.push_back("Jack");
v.push_back("Mike");
v.push_back("Tom");
cout<<v[0]<<endl;//Jack
cout<<v[1]<<endl;//Mike
cout<<v[2]<<endl;//Tom
cout<<v[0][0]<<endl;//J
cout<<v[1][0]<<endl;//M
cout<<v[2].length()<<endl;//3

###2.14string 类型的数字化处理
将读入的数据当成字符串来处理

string s;
s="1234059";
int i;
int sum=0;
for(i=0;i<s.length();i++)
{
if(s[i]=='0')sum+=0;
else if(s[i]=='1')sum+=1;
else if(s[i]=='2')sum+=2;
else if(s[i]=='3')sum+=3;
else if(s[i]=='4')sum+=4;
else if(s[i]=='5')sum+=5;
else if(s[i]=='6')sum+=6;
else if(s[i]=='7')sum+=7;
else if(s[i]=='8')sum+=8;
else if(s[i]=='9')sum+=9;
}
cout<<sum<<endl;//24

###2.15string 对象与字符数组互操作
字符数组与 string 对象的输入与输出

string s;
char ss[100];
//输入字符串到字符数组中
scanf("%s",&ss);
//字符数组赋值线字符串对象
s=ss;
//用 printf 输出字符串对象,要采用 c_str()方法
printf(s.c_str());
//用 printf 输出字符数组
printf("%s",ss);
//用 cout 输出字符串对象
cout<<s<<endl;
//用 cout 输出字符数组
cout<<ss<<endl;

###2.16string 对象与 sscanf 函数
在 C 语言中, sscanf 函数很管用,它可以把一个字符串按你需要的方式分离出子串,
甚至是数字。

string s1,s2,s3;
char sa[100],sb[100],sc[100];
//将字符串分离成子串,分隔符为空格
sscanf("abc 123 pc","%s %s %s",sa,sb,sc);
s1=sa;
s2=sb;
s3=sc;
cout<<s1<<" "<<s2<<" "<<s3<<endl;
//将字符串分离成数字,分隔符为空格
//当用到数字的时候,跟 scanf 一样,它要传指针地址
int a,b,c;
sscanf("1 2 3","%d %d %d",&a,&b,&c);
cout<<a<<" "<<b<<" "<<c<<endl;
//将字符串分离成数字,分隔符为“,”和“$”
//当用到数字的时候,跟 scanf 一样,它要传指针地址
int x,y,z;
sscanf("4,5$6","%d,%d$%d",&x,&y,&z);
cout<<x<<" "<<y<<" "<<z<<endl;
//abc 123 pc
//1 2 3
//4 5 6

###2.17string 对象与数值相互转换
有时候, string 对象与数值之间需要相互转换

#include <iostream>
#include <string>
#include <sstream>
using namespace std;

//C++方法:将数值转换为 string
string convertToString(double x)
{
ostringstream o;
if (o << x)
return o.str();
return "conversion error";//if error
}
//C++方法:将 string 转换为数值
double convertFromString(const string &s)
{
istringstream i(s);
double x;
if (i >> x)
return x;
return 0.0;//if error
}

//将数值转换为 string 的第一种方法: C 方法
char b[10];
string a;
sprintf(b,"%d",1975);
a=b;
cout<<a<<endl;
//将数值转换为 string 的第二种方法: C++方法
string cc=convertToString(1976);
cout<<cc<<endl;
//将 string 转换为数值的方法: C++方法
string dd="2006";
int p=convertFromString(dd)+2;
cout<<p<<endl;

##3.set 集合容器
set 集合容器实现了红黑树(Red-Black Tree)的平衡二叉检索树的数据结构,在插入
元素时,它会自动调整二叉树的排列,把该元素放到适当的位置,以确保每个子树根节点的键值大于左子树所有节点的键值,而小于右子树所有节点的键值;另外,还得确保根节点左子树的高度与右子树的高度相等,这样,二叉树的高度最小,从而检索速度最快。要注意的是,它不会重复插入相同键值的元素,而采取忽略处理。这里写图片描述
平衡二叉检索树的检索使用中序遍历算法, 检索效率高于 vector、 deque 和 list 等容器。
另外,采用中序遍历算法可将键值由小到大遍历出来,所以,可以理解为平衡二叉检索树在插入元素时,就会自动将元素按键值由小到大的顺序排列。
对于 set 容器中的键值,不可直接去修改。因为如果把容器中的一个键值修改了, set
容器会根据新的键值旋转子树,以保持新的平衡,这样,修改的键值很可能就不在原先那个位置上了。换句话来说,构造 set 集合的主要目的就是为了快速检索。
multiset(多重集合容器)、 map(映照容器)和 multimap(多重映照容器)的内部结构也是平衡二叉检索树。
使用 set 前,需要在程序的头文件中包含声明**“#include <set>”**; set 文件在 C:\ProgramFiles\Microsoft Visual Studio\VC98\Include 文件夹中, 它包含了 set 和 multiset 两种容器的定义。
###3.1创建 set 集合对象
创建 set 对象时,需要指定元素的类型,这一点与其他容器一样。

//定义元素类型为 int 的集合对象 s,当前没有任何元素
//元素的排列采用默认的比较规则,当然,可以自定义比较规则函数
set<int> s;

###3.2元素的插入与中序遍历
采用 insert()方法把元素插入集合中去,插入的具体规则在默认的比较规则下,是按元
素值由小到大插入,如果自己指定了比较规则函数,则按自定义比较规则函数插入。
使用前向迭代器对集合中序遍历,其结果正好是元素排序的结果。

//定义元素类型为 int 的集合对象 s,当前没有任何元素
set<int> s;
//插入了 5 个元素,但由于 8 有重复,第二次插入的 8 并没有执行
s.insert(8);//第一次插入 8,可以插入
s.insert(1);
s.insert(12);
s.insert(6);
s.insert(8);//第二次插入 8,重复元素,不会插入
//中序遍历集合中的元素
set<int>::iterator it;//定义前向迭代器
//中序遍历集合中的所有元素
for(it=s.begin();it!=s.end();it++)
{
cout<<*it<<" ";
}
//1 6 8 12

###3.3元素的反向遍历
使用反向迭代器 reverse_iterator 可以反向遍历集合,输出的结果正好是集合元素的反
向排序结果。它需要用到 rbegin()和 rend()两个方法,它们分别给出了反向遍历的开始位置和结束位置。

set<int>::reverse_iterator rit;//定义反向迭代器
for(rit=s.rbegin();rit!=s.rend();rit++)
{
cout<<*rit<<" ";
}

###3.4元素的删除
与插入元素的处理一样,集合具有高效的删除处理功能,并自动重新调整内部的红黑
树的平衡。
删除的对象可以是某个迭代器位置上的元素、等于某键值的元素、一个区间上的元素
和清空集合。

//删除键值为 6 的那个元素
s.erase(6);
//清空集合
s.clear();

###3.5元素的检索
使用 find()方法对集合进行搜索,如果找到查找的键值,则返回该键值的迭代器位置,
否则,返回集合最后一个元素后面的一个位置,即 end()。

set<int>::iterator it;//定义前向迭代器
//查找键值为 6 的元素
it=s.find(6);
if(it!=s.end())//找到
cout<<*it<<endl;
else//没找到
cout<<"not find it"<<endl;
//查找键值为 20 的元素
it=s.find(20);
if(it!=s.end())//找到
cout<<*it<<endl;
else//没找到
cout<<"not find it"<<endl;
//6
//not find it

###3.6自定义比较函数
使用 insert()将元素插入到集合中去的时候,集合会根据设定的比较函数将该元素放到
该放的节点上去。在定义集合的时候,如果没有指定比较函数,那么采用默认的比较函数,即按键值由小到大的顺序插入元素。在很多情况下,需要自己编写比较函数。

//自定义比较函数 myComp,重载“()”操作符
struct myComp
{
bool operator()(const int &a,const int &b)
{
if(a!=b)
return a>b;
else
return a>b;
}
};


//定义元素类型为 int 的集合对象 s,当前没有任何元素
//采用的比较函数是 myComp
set<int,myComp> s;
//插入了 5 个元素,但由于 8 有重复,所以第二次插入的 8 并没有执行
s.insert(8);//第一次插入 8,可以插入
s.insert(1);
s.insert(12);
s.insert(6);
s.insert(8);//第二次插入 8,重复元素,不会插入
set<int,myComp>::iterator it;//定义前向迭代器
for(it=s.begin();it!=s.end();it++)
{
cout<<*it<<" ";
}
//12 8 6 1

(2)如果元素是结构体,那么,可以直接把比较函数写在结构体内。

struct Info
{
string name;
float score;
//重载“<”操作符,自定义排序规则
bool operator < (const Info &a) const
{
//按 score 由大到小排列。如果要由小到大排列,使用“>”号即可。
return a.score<score;
}
};

//定义元素类型为 Info 结构体的集合对象 s,当前没有任何元素
set<Info> s;
//定义 Info 类型的元素
Info info;
//插入 3 个元素
info.name="Jack";
info.score=80.5;
s.insert(info);
info.name="Tomi";
info.score=20.5;
s.insert(info);
info.name="Nacy";
info.score=60.5;
s.insert(info);
set<Info>::iterator it;//定义前向迭代器
for(it=s.begin();it!=s.end();it++)
{
cout<<(*it).name<<" : "<<(*it).score<<endl;
}
//Jack : 80.5
//Nacy : 60.5
//Tomi : 20.5

##4.multiset 多重集合容器
multiset 与 set 一样,也是使用红黑树来组织元素数据的,唯一不同的是, multiset 允
许重复的元素键值插入,而 set 则不允许。
multiset 也需声明头文件包含**“#include <se>”**,由于它包含重复元素,所以,在插入元素、删除元素、查找元素上较 set 有差别。
Alt text
###4.1multiset 元素的插入
插入了重复键值“123”,最后中序遍历了 multiset 对象。

//定义元素类型为 string 的多重集合对象 s,当前没有任何元素
multiset<string> ms;
ms.insert("abc");
ms.insert("123");
ms.insert("111");
ms.insert("aaa");
ms.insert("123");
multiset<string>::iterator it;
for(it=ms.begin();it!=ms.end();it++)
{
cout<<*it<<endl;
}
//111
//123
//123
//aaa
//abc

###4.2multiset 元素的删除
采用 erase()方法可以删除 multiset 对象中的某个迭代器位置上的元素、某段迭代器区
间中的元素、键值等于某个值的所有重复元素,并返回删除元素的个数。采用 clear()方法可以清空元素。

//定义元素类型为 string 的多重集合对象 s,当前没有任何元素
multiset<string> ms;
ms.insert("abc");
ms.insert("123");
ms.insert("111");
ms.insert("aaa");
ms.insert("123");
multiset<string>::iterator it;
for(it=ms.begin();it!=ms.end();it++)
{
cout<<*it<<endl;
}
//删除值为“123”的所有重复元素,返回删除元素总数 2
int n=ms.erase("123");
cout<<"Total deleted : "<<n<<endl;
//输出删除后的剩余元素
cout<<"all elements after deleted :"<<endl;
for(it=ms.begin();it!=ms.end();it++)
{
cout<<*it<<endl;
}
/**
111
123
123
aaa
abc
Total deleted : 2
all elements after deleted :
111
aaa
abc
**/

###4.3查找元素
使用 find()方法查找元素,如果找到,则返回该元素的迭代器位置(如果该元素存在
重复,则返回第一个元素重复元素的迭代器位置);如果没有找到,则返回 end()迭代
器位置。

//定义元素类型为 string 的多重集合对象 s,当前没有任何元素
multiset<string> ms;
ms.insert("abc");
ms.insert("123");
ms.insert("111");
ms.insert("aaa");
ms.insert("123");
multiset<string>::iterator it;
//查找键值“123”
it=ms.find("123");
if(it!=ms.end())//找到
{
cout<<*it<<endl;
}
else//没有找到
{
cout<<"not find it"<<endl;
}
it=ms.find("bbb");
if(it!=ms.end())//找到
{
cout<<*it<<endl;
}
else//没有找到
{
cout<<"not find it"<<endl;
}
//123
//not find it

##5.map 映照容器
map 映照容器的元素数据是由一个键值和一个映照数据组成的,键值与映照数据之间
具有一一映照的关系。
map 映照容器的数据结构也是采用红黑树来实现的,插入元素的键值不允许重复,比
较函数只对元素的键值进行比较,元素的各项数据可通过键值检索出来。由于 map 与 set采用的都是红黑树的数据结构
这里写图片描述
使用 map 容器需要头文件包含语句**“#include <map>”**,map 文件在 C:\ProgramFiles\Microsoft Visual Studio\VC98\Include 文件夹内。map 文件也包含了对 multimap 多重映照容器的定义。
###5.1map 创建、元素插入和遍历访问
创建 map 对象,键值与映照数据的类型由自己定义。在没有指定比较函数时,元素的
插入位置是按键值由小到大插入到黑白树中去的,这点和 set 一样。

//定义 map 对象,当前没有任何元素
map<string,float> m;
//插入元素,按键值的由小到大放入黑白树中
m["Jack"]=98.5;
m["Bomi"]=96.0;
m["Kate"]=97.5;
//前向遍历元素
map<string,float>::iterator it;
for(it=m.begin();it!=m.end();it++)
{
//输出键值与映照数据
cout<<(*it).first<<" : "<<(*it).second<<endl;
}
/**
Bomi : 96
Jack : 98.5
Kate : 97.5
**/

程序编译时,会产生代号为“warning C4786”的警告,“4786”是标记符超长警告的
代号。可以在程序的头文件包含代码的前面使用“#pragma warning(disable:4786)”宏语句,强制编译器忽略该警告。4786 号警告对程序的正确性和运行并无影响。
###5.2删除元素
与 set 容器一样,map 映照容器的 erase()删除元素函数,可以删除某个迭代器位置上
的元素、等于某个键值的元素、一个迭代器区间上的所有元素,当然,也可使用 clear()方法清空 map 映照容器。

//删除键值为 28 的元素
m.erase(28);

###5.3元素反向遍历
可以使用反向迭代器 reverse_iterator 反向遍历 map 照映容器中的数据,它需要 rbegin()方法和 rend()方法指出反向遍历的起始位置和终止位置。

//反向遍历元素
map<int,char>::reverse_iterator rit;
for(rit=m.rbegin();rit!=m.rend();rit++)
{
//输出键值与映照数据
cout<<(*rit).first<<" : "<<(*rit).second<<endl;
}

###5.4元素的搜索
使用 find()方法来搜索某个键值,如果搜索到了,则返回该键值所在的迭代器位置,
否则,返回 end()迭代器位置。由于 map 采用黑白树数据结构来实现,所以搜索速度是极快的。

map<int,char>::iterator it;
it=m.find(28);
if(it!=m.end())//搜索到该键值
{
cout<<(*it).first<<" : "<<(*it).second<<endl;
}
else
{
cout<<"not found it"<<endl;
}
//28 : k

###5.5自定义比较函数
将元素插入到 map 中去的时候,map 会根据设定的比较函数将该元素放到该放的节点
上去。在定义 map 的时候,如果没有指定比较函数,那么采用默认的比较函数,即按键值由小到大的顺序插入元素。在很多情况下,需要自己编写比较函数。
编写比较函数与 set 比较函数是一致的,因为它们的内部数据结构都是红黑树。
(1)如果元素不是结构体,那么,可以编写比较函数。下面这个程序编写的比较规则
是要求按键值由大到小的顺序将元素插入到 map 中:

//自定义比较函数 myComp
struct myComp
{
bool operator()(const int &a,const int &b)
{
if(a!=b)return a>b;
else
return a>b;
}
};


//定义 map 对象,当前没有任何元素
map<int,char,myComp> m;
//插入元素,按键值的由小到大放入黑白树中
m[25]='m';
m[28]='k';
m[10]='x';
m[30]='a';
//使用前向迭代器中序遍历 map
map<int,char,myComp>::iterator it;
for(it=m.begin();it!=m.end();it++)
{
cout<<(*it).first<<" : "<<(*it).second<<endl;
}

/***
30 : a
28 : k
25 : m
10 : x
**/

(2)如果元素是结构体,那么,可以直接把比较函数写在结构体内。

struct Info
{
string name;
float score;
//重载“<”操作符,自定义排序规则
bool operator < (const Info &a) const
{
//按 score 由大到小排列。如果要由小到大排列,使用“>”号即可
return a.score<score;
}
};


//定义 map 对象,当前没有任何元素
map<Info,int> m;
//定义 Info 结构体变量
Info info;
//插入元素,按键值的由小到大放入黑白树中
info.name="Jack";
info.score=60;
m[info]=25;
info.name="Bomi";
info.score=80;
m[info]=10;
info.name="Peti";
info.score=66.5;
m[info]=30;
//使用前向迭代器中序遍历 map
map<Info,int>::iterator it;
for(it=m.begin();it!=m.end();it++)
{
cout<<(*it).second<<" : ";
cout<<((*it).first).name<<" "<<((*it).first).score<<endl;
}
/**
10 : Bomi 80
30 : Peti 66.5
25 : Jack 60
**/

###5.6用 map 实现数字分离
对数字的各位进行分离,采用取余等数学方法操作是很耗时的。而把数字当成字符串,使用 map 的映照功能,很方便地实现了数字分离。

//定义 map 对象,当前没有任何元素
map<char,int> m;
//赋值:字符映射数字
m['0']=0;
m['1']=1;
m['2']=2;
m['3']=3;
m['4']=4;
m['5']=5;
m['6']=6;
m['7']=7;
m['8']=8;
m['9']=9;
/*上面的 10 条赋值语句可采用下面这个循环来简化代码编写
for(int j=0;j<10;j++)
{
m['0'+j]=j;
}
*/
string sa,sb;
sa="6234";
int i;
int sum=0;
for(i=0;i<sa.length();i++)
{
sum+=m[sa[i]];
}
cout<<"sum = "<<sum<<endl;
//sum = 15

###5.7数字映照字符的 map 写法
在很多情况下,需要实现将数字映射为相应的字符

//定义 map 对象,当前没有任何元素
map<int,char> m;
//赋值:字符映射数字
m[0]='0';
m[1]='1';
m[2]='2';
m[3]='3';
m[4]='4';
m[5]='5';
m[6]='6';
m[7]='7';
m[8]='8';
m[9]='9';
/*上面的 10 条赋值语句可采用下面这个循环来简化代码编写
for(int j=0;j<10;j++)
{
m[j]='0'+j;
}
*/
int n=7;
string s="The number is ";
cout<<s + m[n]<<endl;
//The number is 7

##6.multimap 多重映照容器
multimap 与 map 基本相同,唯独不同的是,multimap 允许插入重复键值的元素。由于允许重复键值存在,所以,multimap 的元素插入、删除、查找都与 map 不相同。
要使用 multimap,则需要头文件包含语句**“#include <map>”**。map 文件在 C:\ProgramFiles\Microsoft Visual Studio\VC98\Include 文件夹中。
###6.1multimap 对象创建、元素插入
可以重复插入元素,插入元素需要使用 insert()方法。

//定义 map 对象,当前没有任何元素
multimap<string,double> m;
//插入元素
m.insert(pair<string,double>("Jack",300.5));
m.insert(pair<string,double>("Kity",200));
m.insert(pair<string,double>("Memi",500));
//重复插入键值“Jack”
m.insert(pair<string,double>("Jack",306));
//使用前向迭代器中序遍历 multimap
multimap<string,double>::iterator it;
for(it=m.begin();it!=m.end();it++)
{
cout<<(*it).first<<" : "<<(*it).second<<endl;
}
/**
Jack : 300.5
Jack : 306
Kity : 200
Memi : 500
**/

###6.2元素的删除
删除操作采用 erase()方法,可删除某个迭代器位置上的元素、等于某个键值的所有重
复元素、一个迭代器区间上的元素。使用 clear()方法可将 multimap 容器中的元素清空。
因为有重复的键值,所以,删除操作会将要删除的键值一次性从 multimap 中删除。

//删除键值等于“Jack”的元素
m.erase("Jack");

###6.3元素的查找
由于 multimap 存在重复的键值,所以 find()方法只返回重复键值中的第一个元素的迭
代器位置,如果没有找到该键值,则返回 end()迭代器位置。

it=m.find("Jack");
if(it!=m.end())//找到
{
cout<<(*it).first<<" "<<(*it).second<<endl;
}
else//没找到
{
cout<<"not find it"<<endl;
}
it=m.find("Nacy");
if(it!=m.end())//找到
{
cout<<(*it).first<<" "<<(*it).second<<endl;
}
else//没找到
{
cout<<"not find it"<<endl;
}
//Jack 300.5
//not find it

##7.deque 双端队列容器
deque 双端队列容器与 vector 一样,采用线性表顺序存储结构。但与 vector 唯一不同
的是,deque 采用分块的线性存储结构来存储数据,每块的大小一般为 512 字节,称为一个 deque 块,所有的 deque 块使用一个 Map 块进行管理,每个 Map 数据项记录各个 deque块的首地址。这样一来,deque 块在头部和尾部都可插入和删除元素,而不需移动其他元素(使用 push_back()方法在尾部插入元素,会扩张队列;而使用 push_front()方法在首部插入元素和使用 insert()方法在中间插入元素,只是将原位置上的元素值覆盖,不会增加新元素)。一般来说,当考虑到容器元素的内存分配策略和操作的性能时,deque 相对于 vector更有优势。
这里写图片描述
使用 deque 需要声明头文件包含**“#include <deque>”**,文件 deque 在 C:\ProgramFiles\Microsoft Visual Studio\VC98\Include 文件夹中。
###7.1创建 deque 对象
创建 deque 对象的方法通常有三种。
(1)创建没有任何元素的 deque 对象,如:

deque<int> d;
deque<float> dd;

(2)创建具有 n 个元素的 deque 对象,如:

deque<int> d(10);//创建具有 10 个整型元素的 deque 对象 d

(3)创建具有 n 个元素的 deque 对象,并赋初值,如:

deque<int> d(108.5);
//创建具有 10 个整型元素的 deque 对象 d,每个元素值为 8.5

###7.2插入元素
(1)使用 push_back()方法从尾部插入元素,会不断扩张队列。

//定义 deque 对象,元素类型是整型
deque<int> d;
//从尾部连续插入三个元素
d.push_back(1);
d.push_back(2);
d.push_back(3);
//以数组方式输出元素
cout<<d[0]<<" "<<d[1]<<" "<<d[2]<<endl;
//1 2 3

(2)从头部插入元素,不会增加新元素,只将原有的元素覆盖。

//定义 deque 对象,元素类型是整型
deque<int> d;
//从尾部连续插入三个元素
d.push_back(1);
d.push_back(2);
d.push_back(3);
//从头部插入元素,不会增加新元素,只将原有的元素覆盖
d.push_front(10);
d.push_front(20);
//以数组方式输出元素
cout<<d[0]<<" "<<d[1]<<" "<<d[2]<<" "<<d[3]<<" "<<d[4]<<endl;
//20 10 1 2 3

(3)从中间插入元素,不会增加新元素,只将原有的元素覆盖。

//定义 deque 对象,元素类型是整型
deque<int> d;
//从尾部连续插入三个元素
d.push_back(1);
d.push_back(2);
d.push_back(3);
//中间插入元素,不会增加新元素,只将原有的元素覆盖
d.insert(d.begin()+1,88);
//以数组方式输出元素
cout<<d[0]<<" "<<d[1]<<" "<<d[2]<<endl;
//1 88 2

###7.3前向遍历
(1)以数组方式遍历。

//定义 deque 对象,元素类型是整型
deque<int> d;
//从尾部连续插入三个元素
d.push_back(1);
d.push_back(2);
d.push_back(3);
//以数组方式输出元素
int i;
for(i=0;i<d.size();i++)
{
cout<<d[i]<<" ";
}
//1 2 3

(2)以前向迭代器的方式遍历。

//定义 deque 对象,元素类型是整型
deque<int> d;
//从尾部连续插入三个元素
d.push_back(1);
d.push_back(2);
d.push_back(3);
//以前向迭代器的方式遍历
deque<int>::iterator it;
for(it=d.begin();it!=d.end();it++)
{
cout<<*it<<" ";
}
//1 2 3

###7.4反向遍历
采用反向迭代器对双端队列容器进行反向遍历。

//定义 deque 对象,元素类型是整型
deque<int> d;
//从尾部连续插入三个元素
d.push_back(1);
d.push_back(2);
d.push_back(3);
//以反向迭代器的方式遍历
deque<int>::reverse_iterator rit;
for(rit=d.rbegin();rit!=d.rend();rit++)
{
cout<<*rit<<" ";
}
//3 2 1

###7.5删除元素
可以从双端队列容器的首部、尾部、中部删除元素,并可以清空双端队列容器。
(1)采用 pop_front()方法从头部删除元素。

//定义 deque 对象,元素类型是整型
deque<int> d;
//从尾部连续插入五个元素
d.push_back(1);
d.push_back(2);
d.push_back(3);
d.push_back(4);
d.push_back(5);
//从头部删除元素
d.pop_front();
d.pop_front();
//以前向迭代器的方式遍历
deque<int>::iterator it;
for(it=d.begin();it!=d.end();it++)
{
cout<<*it<<" ";
}
//3 4 5

(2)采用 pop_back()方法从尾部删除元素。

//定义 deque 对象,元素类型是整型
deque<int> d;
//从尾部连续插入五个元素
d.push_back(1);
d.push_back(2);
d.push_back(3);
d.push_back(4);
d.push_back(5);
//从尾部删除元素
d.pop_back();
//以前向迭代器的方式遍历
deque<int>::iterator it;
for(it=d.begin();it!=d.end();it++)
{
cout<<*it<<" ";
}
//1 2 3 4

(3)使用 erase()方法从中间删除元素,其参数是迭代器位置。

//定义 deque 对象,元素类型是整型
deque<int> d;
//从尾部连续插入五个元素
d.push_back(1);
d.push_back(2);
d.push_back(3);
d.push_back(4);
d.push_back(5);
//从中间删除元素,erase 的参数是迭代器位置
d.erase(d.begin()+1);
//以前向迭代器的方式遍历
deque<int>::iterator it;
for(it=d.begin();it!=d.end();it++)
{
cout<<*it<<" ";
}
// 1 3 4 5

(4)使用 clear()方法清空 deque 对象。

//定义 deque 对象,元素类型是整型
deque<int> d;
//从尾部连续插入五个元素
d.push_back(1);
d.push_back(2);
d.push_back(3);
d.push_back(4);
d.push_back(5);
//清空元素
d.clear();
//输出元素的个数
cout<<d.size()<<endl;
//0

##8.list 双向链表容器
list 容器实现了双向链表的数据结构,数据元素是通过链表指针串连成逻辑意义上的线性表,这样,对链表的任一位置的元素进行插入、删除和查找都是极快速的。
这里写图片描述
list 的每个节点有三个域:前驱元素指针域、数据域和后继元素指针域。前驱元素指针域保存了前驱元素的首地址;数据域则是本节点的数据;后继元素指针域则保存了后继元素的首地址。list 的头节点的前驱元素指针域保存的是链表中尾元素的首地址,而 list 的尾节点的后继元素指针域则保存了头节点的首地址,这样,就构成了一个双向循环链。
由于 list 对象的节点并不要求在一段连续的内存中,所以,对于迭代器,只能通过“++”或“- -”的操作将迭代器移动到后继/前驱节点元素处。而不能对迭代器进行+n 或-n 的操作,这点,是与 vector 等不同的地方。
使用 list 需要声明头文件包含**“#include <list>”**,list 文件在 C:\Program Files\MicrosoftVisual Studio\VC98\Include 文件夹中。
###8.1创建 list 对象
(1)创建空链表,如:

list<int> l;

(2)创建具有 n 个元素的链表,如:

list<int> l(10; //创建具有 10 个元素的链表

###8.2元素插入和遍历
有三种方法往链表里插入新元素:
(1)采用 push_back()方法往尾部插入新元素,链表自动扩张。
(2)采用 push_front()方法往首部插入新元素,链表自动扩张。
(3)采用 insert()方法往迭代器位置处插入新元素,链表自动扩张。注意,迭代器只能进行“++”或“- -”操作,不能进行+n 或-n 的操作,因为元素的位置并不是物理相连的。
采用前向迭代器 iterator 对链表进行遍历。

//定义元素为整型的 list 对象,当前没有元素
list<int> l;
//在链表尾部插入新元素,链表自动扩张
l.push_back(2);
l.push_back(1);
l.push_back(5);
//在链表头部插入新元素,链表自动扩张
l.push_front(8);
//在任意位置插入新元素,链表自动扩张
list<int>::iterator it;
it=l.begin();
it++;//注意,链表的迭代器只能进行++或--操作,而不能进行+n 操作
l.insert(it,20);
//使用前向迭代器遍历链表
for(it=l.begin();it!=l.end();it++)
{
cout<<*it<<" ";
}

###8.3反向遍历
采用反向迭代器 reverse_iterator 对链表进行反向遍历。

//定义元素为整型的 list 对象,当前没有元素
list<int> l;
//在链表尾部插入新元素,链表自动扩张
l.push_back(2);
l.push_back(1);
l.push_back(5);
//反向遍历链表
list<int>::reverse_iterator rit;
for(rit=l.rbegin();rit!=l.rend();rit++)
{
cout<<*rit<<" ";
}
//5 1 2

###8.4元素删除
(1)可以使用 remove()方法删除链表中一个元素,值相同的元素都会被删除。

//删除值等于 10 的所有元素
l.remove(10);

(2)使用 pop_front()方法删除链表首元素,使用 pop_back()方法删除链表尾元素。

//删除首元素
l.pop_front();
//删除尾元素
l.pop_back();

(3)使用 erase()方法删除迭代器位置上的元素。

list<int>::iterator it;
l.erase(it.begin()+2);//删除第二个元素

(4)使用 clear()方法清空链表。

//清空链表
l.clear();

###8.5元素查找
采用 find()查找算法可以在链表中查找元素,如果找到该元素,返回的是该元素的迭代器位置;如果没有找到,则返回 end()迭代器位置。
find()算法需要声明头文件包含语句“#include <algorithm>”。

//定义元素为整型的 list 对象,当前没有元素
list<int> l;
//在链表尾部插入新元素,链表自动扩张
l.push_back(2);
l.push_back(8);
l.push_back(1);
l.push_back(5);
l.push_back(1);
//遍历链表
list<int>::iterator it,it2;
for(it=l.begin();it!=l.end();it++)
{
cout<<*it<<" ";
}
//回车换行
cout<<endl;
//采用 find()查找算法在链表中查找
it=find(l.begin(),l.end(),5);
if(it!=l.end())//找到
{
cout<<"find it"<<endl;
}
else
{
cout<<"not find it"<<endl;
}
it=find(l.begin(),l.end(),10);
if(it!=l.end())//找到
{
cout<<"find it"<<endl;
}
else
{
cout<<"not find it"<<endl;
}
/**
2 8 1 5 1
find it
not find it
**/

###8.6元素排序
采用 sort()方法可以对链表元素进行升序排列。

//定义元素为整型的 list 对象,当前没有元素
list<int> l;
//在链表尾部插入新元素,链表自动扩张
l.push_back(2);
l.push_back(8);
l.push_back(1);
l.push_back(5);
l.push_back(1);
//遍历链表
list<int>::iterator it,it2;
for(it=l.begin();it!=l.end();it++)
{
cout<<*it<<" ";
}
//回车换行
cout<<endl;
//使用 sort()方法对链表排序,是升序排列
l.sort();
//遍历链表
for(it=l.begin();it!=l.end();it++)
{
cout<<*it<<" ";
}
/**
2 8 1 5 1
1 1 2 5 8
**/

###8.7剔除连续重复元素
采用 unique()方法可以剔除连续重复元素,只保留一个。

//定义元素为整型的 list 对象,当前没有元素
list<int> l;
//在链表尾部插入新元素,链表自动扩张
l.push_back(2);
l.push_back(8);
l.push_back(1);
l.push_back(1);
l.push_back(1);
l.push_back(5);
l.push_back(1);
//遍历链表
list<int>::iterator it,it2;
for(it=l.begin();it!=l.end();it++)
{
cout<<*it<<" ";
}
//回车换行
cout<<endl;
//剔除连续重复元素(只保留一个)
l.unique();
//遍历链表
for(it=l.begin();it!=l.end();it++)
{
cout<<*it<<" ";
}
/**
2 8 1 1 1 5 1
2 8 1 5 1
**/

##9.bitset 位集合容器
bitset 容器是一个 bit 位元素的序列容器,每个元素只占一个 bit 位,取值为 0 或 1,因而很节省内存空间。
这里写图片描述
使用 bitset,需要声明头文件包含语句**“#include <bitset>”**, bitset 文件在 C:\ProgramFiles\Microsoft Visual Studio\VC98\Include 文件夹下。
这里写图片描述
###9.1创建 bitset 对象
创建 bitset 对象时,必须要指定容器的大小。 bitset 对象的大小一经定义,就不能修改了。

bitset<100000> b;
//定义了 bitset 对象 b, 它能容纳 100 000 个元素, 即 100 000 个 bit (位),此时,所有元素的值都为 0。

###9.2设置元素值
(1)采用下标法。

bitset<10> b;
//采用下标法给元素赋值
b[1]=1;
b[6]=1;
b[9]=1;
//下标法输出所有元素,第 0 位是最低位,第 9 位是最高位
//1001000010

(2)采用 set()方法,一次性将元素设置为 1。

bitset<10> b;
//采用 set()方法,一次性将元素设置为 1
b.set();
//下标法输出所有元素,第 0 位是最低位,第 9 位是最高位
int i;
for(i=b.size()-1;i>=0;i--)
{
cout<<b[i];
}
//1111111111

(3)采用 set(pos)方法,将某 pos 位设置为 1。

bitset<10> b;
//采用 set(pos)方法,将元素设置为 1
b.set(1,1);
b.set(6,1);
b.set(9,1);
//下标法输出所有元素,第 0 位是最低位,第 9 位是最高位
//1001000010

###9.3输出元素
(1)采用下标法输出元素。


bitset<10> b;
//采用 set()方法,将元素全部设置为 1
b.set();
//采用 set(pos)方法,将元素设置为 0
b.set(0,0);
b.set(2,0);
b.set(3,0);
b.set(4,0);
b.set(5,0);
b.set(7,0);
b.set(8,0);
//下标法输出所有元素,第 0 位是最低位,第 9 位是最高位
int i;
for(i=b.size()-1;i>=0;i--)
{
cout<<b[i];
}
//1001000010

(2)直接向输出流输出全部元素。

bitset<10> b;
//采用 set()方法,将元素全部设置为 1
b.set();
//采用 set(pos)方法,将元素设置为 0
b.set(0,0);
b.set(2,0);
b.set(3,0);
b.set(4,0);
b.set(5,0);
b.set(7,0);
b.set(8,0);
//直接向输出流输出全部元素
cout<<b<<endl;
//1001000010

##10.stack 堆栈容器
stack 堆栈是一个后进先出(Last In First Out, LIFO)的线性表,插入和删除元素都只能在表的一端进行。插入元素的一端称为栈顶(Stack Top),而另一端则称为栈底(StackBottom)。插入元素叫入栈(Push),元素的删除则称为出栈(Pop)。
这里写图片描述
要使用 stack,必须声明头文件包含语句**“#include <stack>”**。 stack 文件在 C:\ProgramFiles\Microsoft Visual Studio\VC98\Include 文件夹中。
堆栈的使用方法
堆栈只提供入栈、出栈、栈顶元素访问和判断是否为空等几种方法。

  • 采用 push()方法将元素入栈;采用 pop()方法出栈;
  • 采用 top()方法访问栈顶元素;
  • 采用empty()方法判断堆栈是否为空,如果是空的,则返回逻辑真,否则返回逻辑假;
  • 采用 size()方法返回当前堆栈中有几个元素.
//定义堆栈 s,其元素类型是整型
stack<int> s;
//元素入栈
s.push(1);
s.push(2);
s.push(3);
s.push(9);
//读取栈顶元素
cout<<s.top()<<endl;
//返回堆栈元素数量
cout<<s.size()<<endl;
//判断堆栈是否为空
cout<<s.empty()<<endl;
//所有元素出栈(删除所有元素)
while(s.empty()!=true)//堆栈非空
{
cout<<s.top()<<" ";//读取栈顶元素
s.pop();//出栈(即删除栈顶元素)
}
/**
9
4
0
9 3 2 1
**/

##11.queue 队列容器
queue 队列容器是一个先进先出(First In First Out, FIFO)的线性存储表,元素的插入只能在队尾,元素的删除只能在队首
这里写图片描述
使用 queue 需要声明头文件包含语句**“#include <queue>”**, queue 文件在 C:\ProgramFiles\Microsoft Visual Studio\VC98\Include 文件夹里。
queue 队列的使用方法
queue 队列具有入队 push()(即插入元素)、出队 pop()(即删除元素)、读取队首元素 front()、读取队尾元素 back()、判断队列是否为空 empty()和队列当前元素的数目 size()这几种方法。

//定义队列,元素类型是整型
queue<int> q;
//入队,即插入元素
q.push(1);
q.push(2);
q.push(3);
q.push(9);
//返回队列元素数量
cout<<q.size()<<endl;
//队列是否为空,是空,则返回逻辑真,否则返回逻辑假
cout<<q.empty()<<endl;
//读取队首元素
cout<<q.front()<<endl;
//读取队尾元素
cout<<q.back()<<endl;
//所有的元素出列(删除所有元素)
while(q.empty()!=true)
{
cout<<q.front()<<" ";
//队首元素出队(删除队首元素)
q.pop();
}
/**
4
0
1
9
1 2 3 9
**/

##12.priority_queue 优先队列容器
priority_queue 优先队列容器与队列一样,只能从队尾插入元素,从队首删除元素。但它有一个特性,就是队列中最大的元素总是位于队首,所以出队时,并非按先进先出的原则进行,而是将当前队列中最大的元素出队。这点类似于给队列里的元素进行了由大到小的顺序排序。元素的比较规则默认为按元素的值由大到小排序;当然,可以重载“<”操作符来重新定义比较规则。
使用 priority_queue 需要声明头文件包含语句**“#include <queue>”**,它与 queue 队列共用一个头文件, queue 文件在 C:\Program Files\Microsoft Visual Studio\VC98\Include 文件夹中。
###12.1优先队列的使用方法
优先队列包含入队 push()(插入元素)、出队 pop()(删除元素)、读取队首元素 top()、判断队列是否为空 empty()和读取队列元素数量 size()等方法。

//定优先队列,元素类型为整型
priority_queue<int> pq;
//入队,插入新元素
pq.push(1);
pq.push(2);
pq.push(3);
pq.push(9);
//返回队列中元素数目
cout<<pq.size()<<endl;
//所有元素出队,删除所有元素
while(pq.empty()!=true)
{
//读取当前队首元素
cout<<pq.top()<<" ";
//出队,删除队首元素
pq.pop();
}
/**
4
9 3 2 1
**/

###12.2重载“<”操作符来定义优先级
如果优先队列的元素类型是结构体,可以通过在结构体中重载“<”操作符的方法来修改优先队列的优先性。

//定义结构体
struct Info{
string name;
float score;
//重载“<”操作符,指定优先规则(排序规则)
bool operator < (const Info &a) const
{
//按 score 由小到大排列。如果要由大到小排列,使用“>”号即可
return a.score<score;
}
};

//定义优先队列,元素类型为 Info 结构体
priority_queue<Info> pq;
//定义结构体变量
Info info;
//入队
info.name="Jack";
info.score=68.5;
pq.push(info);
info.name="Bomi";
info.score=18.5;
pq.push(info);
info.name="Peti";
info.score=90;
pq.push(info);
//元素全部出队
while(pq.empty()!=true)
{
//返回队首元素
cout<<pq.top().name<<" : "<<pq.top().score<<endl;
//出队,删除队首元素
pq.pop();
}
/**
Bomi : 18.5
Jack : 68.5
Peti : 90
**/

###12.3重载“()”操作符来定义优先级
如果优先队列的元素不是结构体类型,则可以通过重载“()”操作符的方式来定义优先级。当然,元素是结构体类型,也可以通过重载“()”操作符的方式来定义优先级,而不是一定要在结构体内重载“<”操作符才行。

//重载“()”操作符
struct myComp
{
bool operator()(const int &a,const int &b)
{
//由小到大排列采用“>”号;如果要由大到小排列,则采用“<”号
return a>b;
}
};

//定义优先队列,元素类型为 Info 结构体,显式说明内部结构是 vector
priority_queue<int,vector<int>,myComp> pq;
//入队
pq.push(1);
pq.push(9);
pq.push(2);
pq.push(30);
//元素全部出队
while(pq.empty()!=true)
{
//返回队首元素
cout<<pq.top()<<" ";
//出队,删除队首元素
pq.pop();
}
/**
1 2 9 30
**/
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值