只能访问容器的第一个和最后一个元素
只能在容器的末尾添加新的元素
只能从头部移出元素
先进先出(FIFO,First in first out)
queue<数据类型>名称;
queueq1;
queueq2;
back()返回最后一个元素
empty()如果队列为空返回true
front()返回队首元素
pop()删除队首元素
push()在末尾加入一个元素
size()返回队列中元素的个数
q1.push(1);//向q1这个队列中插入1这个数字
int len=q1.size();
int a=q1.fount();
东秦oj 练手题
题目描述:
队列操作题。根据输入的操作命令,操作队列(1)入队、(2)出队并输出、(3)计算队中元素个数并输出。
输入:
第一行一个数字N。 下面N行,每行第一个数字为操作命令(1)入队、(2)出队并输出、(3)计算队中元素个
数并输出。
输出:
若干行每行显示一个2或3命令的输出结果。注意:2.出队命令可能会出现空队出队(下溢),请输出“no”,并退
出。
#include
using namespace std;
int main()
{
queueq;
int n,a,b;
cin>>n;
while(n--)
{
cin>>a;
if(a==1)
{
cin>>b;
q.push(b);
}
if(a==2)
{
if(!q.empty())
{
cout<
题目描述:
某不对进行新兵队列训练,将新兵从一开始按照顺序依次编号,并排成一行横队,训练的规则如下:
从头开始1到2报数,凡是报到2的就出列,剩下的人向小序号方向靠拢。再从头进行1到3报数,凡是报到3的就出列,剩下的人还是向小序号方向靠拢,继续从头开始从1到2报数。。。
以后从头开始轮流进行1到2,1到3报数,直到剩下的人数不超过3为止。
思路:用队列模拟,
#include
using namespace std;
int main()
{
queueq;
int n,t;
cin>>t;
while(t--)
{
cin>>n;
for(int i=1;i<=n;i++)
q.push(i);
int flag=1;//标记是怎样报数,开始是flag=1;1 2报数
while(q.size()>3)
{
if(flag&1)
{
int num=q.size();//目前有多少人
for(int i=1;i<=num;i++)
{
if(i%2==0)
q.pop();
else
{
q.push(q.front());
q.pop();
}
}
flag=0;//此后就是1 3报数
}
else
{
int num=q.size();
for(int i=1;i<=num;i++)
{
if(i%3==0)
q.pop();
else
{
q.push(q.front());
q.pop();
}
}
flag=1;
}
}
//再控制一下输出格式末尾不能有空格
printf("%d",q.front());
q.pop();
while(!q.empty())
{
printf(" %d",q.front());
q.pop();
}
printf("\n");
}
return 0;
}
pair就是一个结构体,但是比结构体更加灵活,一般使用typedef优化,
pair
pairp1;
pairp2(1,2.5); //定义的同时 还初始化了
pairp3(p2); //拷贝构造函数
p1.first=1;
p1.second=2;
cout<
pairp4;
p4=make_pair(1,2.38);
p5=p4; //变量间赋值
如果一个函数有两个返回值 的话,如果是相同类型,就可以用数组返回,如果是不同类型,就可以自己写个
struct ,但为了方便就可以使用 c++ 自带的pair ,返回一个pair,其中带有两个值。除了返回值的应用,在一个对象
有多个属性的时候 ,一般自己写一个struct ,如果就是两个属性的话,就可以用pair 进行操作
东秦oj
成绩排序
题目大意:输入n个学生的姓名和成绩,排序后输出
题解:这里是每一个数据由两个部分组成:姓名和成绩。
建一个pair
法一:
#include
using namespace std;
typedef pairp;//起个别名
p arr[101];
int n;
bool cmp(p a,p b)
{
return a.second>b.second;
}
int main()
{
cin>>n;
for(int i=0;i>arr[i].first>>arr[i].second;
sort(arr,arr+n,cmp);
for(int i=0;i
还有一个简单写法。 在sort排序的时候,对于pair类型数据默认按照first进行升序排序,所以咱们完全可以把成绩放入first,输出的时候先输出second,再输出first。(就不用自己写自定义比较函数了)
#include
using namespace std;
typedef pair P;
//起个别名 !!!这里有变化,交换数据类型的位置,把int放在first的位置,以便排序
P arr[101]; //结构体数组
int n;
int main()
{
scanf("%d",&n);
for(int i=0;i>arr[i].second>>arr[i].first;
sort(arr,arr+n); //默认升序排序
for(int i=n-1;i>=0;i--) //这里要倒序输出,
cout<
set中元素是排好序的,从小到大(默认升序排列)
set中没有重复元素
//set<数据类型>名称;
sets;
s.begin(); //返回指向容器 最开始位置 数据的 ==指针==
s.end(); //返回指向容器最后一个数据单元 ==+1的指针==
s.insert(); //插入
s.clear(); //清空
s.empty(); //判断set是否为空
s.size(); //返回set中元素的个数
s.erase(); //删除迭代器指针it处元素
s.count(x) //返回x出现的次数(因为是集合 只可能是0或1)
注意:插入规则在默认的比较规则下,是按元素值从小到大插入,如果自己指定了比较规则函数,则按自定义比较规则函数插入。
set::iterator it; //定义前向迭代器
set::reverse_iterator rit; //定义反向迭代器
看这两个代码:
#include
#include
using namespace std;
int main()
{
set s;
s.insert(5); //第一次插入5,可以插入
s.insert(1);
s.insert(6);
s.insert(3);
s.insert(5); //第二次插入5,重复元素,不会插入
set::iterator it; //定义前向迭代器
//中序遍历集合中的所有元素
for(it = s.begin(); it != s.end(); it++)
{
cout << *it << " ";
}
//cout <
第二个代码:
(元素的方向遍历
使用反向迭代器reverse_iterator可以反向遍历集合,输出的结果正好是集合元素的反向排序结果。
它需要用到 rbegin()和rend() 两个方法,
它们分别给出了反向遍历的开始位置和结束位置。)
#include
#include
using namespace std;
int main()
{
set s;
s.insert(5); //第一次插入5,可以插入
s.insert(1);
s.insert(6);
s.insert(3);
s.insert(5); //第二次插入5,重复元素,不会插入
set::reverse_iterator rit; //定义反向迭代器
//反向遍历集合中的所有元素
for(rit = s.rbegin(); rit != s.rend(); rit++)
{
cout << *rit << " ";
}
cout << endl;
return 0;
}
//运行结果:6 5 3 1
与插入元素的处理一样,集合具有高效的删除处理功能,并自动重新调整内部的红黑树的平衡。
删除的对象可以是某个迭代器位置上的元素、等于某键值的元素、一个区间上的元素和清空集合。
#include
#include
using namespace std;
int main()
{
set s;
s.insert(5); //第一次插入5,可以插入
s.insert(1);
s.insert(6);
s.insert(3);
s.insert(5); //第二次插入5,重复元素,不会插入
//此时s中是1,3,5,6
s.erase(6); //删除键值为6的元素
//1,3,5
set::reverse_iterator rit; //定义反向迭代器
//反向遍历集合中的所有元素
for(rit = s.rbegin(); rit != s.rend(); rit++)
{
cout << *rit << " ";
}
cout << endl;
//5,3,1
set::iterator it;
//1,3,5
it = s.begin();
for(int i = 0; i < 2; i++)
it = s.erase(it);
//5
for(it = s.begin(); it != s.end(); it++)
cout << *it << " ";
cout << endl;
/*输出也可以用:
while(!s.empty())
{
cout<<*s.begin()<<" "; //注意此处的用法
s.erase(s.begin());
}
*/
s.clear();
cout << s.size() << endl;
//0
return 0;
}
/*
运行结果:
5 3 1
5
0
*/
使用find()方法对集合进行检索,如果找到查找的的键值,则返回该键值的 迭代器位置 ;否则,返回集合最后一个元素后面的一个位置,即end()。
#include
#include
using namespace std;
int main()
{
set s;
s.insert(5); //第一次插入5,可以插入
s.insert(1);
s.insert(6);
s.insert(3);
s.insert(5); //第二次插入5,重复元素,不会插入
//1,3,5,6
set::iterator it;
it = s.find(6); //查找键值为6的元素
if(it != s.end())
cout << *it << endl;
else
cout << "not find it" << endl;
it = s.find(20);
if(it != s.end())
cout << *it << endl;
else
cout << "not find it" << endl;
return 0;
}
/*
运行结果:
6
not find it
*/
使用insert将元素插入到集合中去的时候,集合会根据设定的比较函数奖该元素放到该放的节点上去。在定义集合的时候,如果没有指定比较函数,那么采用 默认的比较函数,是按键值从小到大的顺序插入元素。但在很多情况下,需要自己编写比较函数。
编写比较函数有两种方法。
(1)如果元素不是结构体,那么可以编写比较函数。下面的程序比较规则为 按键值从大到小的顺序插入到集合中 。
#include
#include
using namespace std;
struct mycomp
{
//自定义比较函数,重载“()”操作符
bool operator() (const int &a, const int &b)
{
if(a != b)
return a > b;
else
return a > b;
}
};
int main()
{
set s; //采用比较函数mycomp
s.insert(5); //第一次插入5,可以插入
s.insert(1);
s.insert(6);
s.insert(3);
s.insert(5); //第二次插入5,重复元素,不会插入
set::iterator it;
for(it = s.begin(); it != s.end(); it++)
cout << *it << " ";
cout << endl;
return 0;
}
/*
运行结果:6 5 3 1
*/
(2)如果元素是结构体,那么可以直接把比较函数写在结构体内。
#include
#include
#include
using namespace std;
struct Info
{
string name;
double score;
bool operator < (const Info &a) const // 重载“<”操作符,自定义排序规则
{
//按score由大到小排序。如果要由小到大排序,使用“>”即可。
return a.score < score;
}
};
int main()
{
set s;
Info info;
//插入三个元素
info.name = "Jack";
info.score = 80;
s.insert(info);
info.name = "Tom";
info.score = 99;
s.insert(info);
info.name = "Steaven";
info.score = 60;
s.insert(info);
set::iterator it;
for(it = s.begin(); it != s.end(); it++)
cout << (*it).name << " : " << (*it).score << endl;
return 0;
}
/*
运行结果:
Tom : 99
Jack : 80
Steaven : 60
*/
只能访问栈顶元素,
插入删除只能在栈顶操作
插入叫入栈,删除叫出栈
后进先出
stack s; //stack<数据类型> 名称;
stack s;
s.empty() //判断栈是否为空
s.size() //返回栈中元素个数
s.pop() //删除栈顶元素
s.top() //返回栈顶元素但不删除该元素
s.push(x) //在栈顶压入新元素
Description
在 Ubuntu 等一系列类似 Linux 系统终端中,输入密码是不可见的,这就需要你记住你所输入的内容。因为是不可见的,有时候可能输入错误,或者自己忘记输入的是什么了,这时你可以通过拼命的按退格键来删除你刚才输入的内容。当然,如果你什么都没有输入或者把之前的东西删光了,按退格键是没有任何效果的。
假设密码允许输入大小写字母和数字, “@”符号代表退格。 现在给你一个包含大小写字母和数字的序列,代表用户的输入,以及一个正确的密码,请聪明的你来实现一个简单的密码比对器, 验证用户的输入和正确密码是否相同。
Input
输入共有两行,分别为正确密码和用户的输入,题目保证用户的输入和正确密码不超过 1000 位,且输入非空。
Output
如果用户的输入与正确密码一致,输出 “True”,否则输出“False”
Sample Input
123456
123abc@@@@@@@@@654321
Sample Output
False
#include
using namespace std;
stackst;
int main()
{
string a,b,s; //a是最终目标,b是要处理的字符串,s是接收处理好的字符串的
//在st栈中遍历b,用s接收处理好的,再与a比较
cin>>a>>b;
int len=b.size();
for(int i=0;i
//默认定义:
priority_queue q;
//手动定义 推荐使用此方法
priority_queue ,less >q; //降序 从大到小
priority_queue ,greater >q; //升序 从小到大
q.size();//返回q里元素个数
q.empty();//返回q是否为空,空则返回1,否则返回0
q.push(k);//在q的末尾插入k
q.pop();//删掉q的第一个元素
q.top();//返回q的第一个元素,不删除
q.back();//返回q的末尾元素
#include
using namespace std;
int main(void)
{
priority_queue,greater > q;
//乱序插入
q.push(3);
q.push(6);
q.push(1);
//遍历
while(!q.empty())
{
cout<
题目大意:
有一堆木棒,最后合成一根,求花费体力最小.
比如长度是3 5 8 合成一个
首先是3和5合成长度为8的,耗费8个体力
此时剩两根木棒8 8
再合成一个8+8耗费16体力
总共耗费8+16=24个体力
题解:思路就是,每次都找两个最小的 ,把他们合成一个,才能保证合成的那个尽量小,保证接下来合成每次都是最优的解,这就是 贪心的思路,局部最优解,达到全局最优解
用优先队列很好实现,每次取队列两个最小值,合成之后插入队列里。直到只剩一根。
#include
#include
using namespace std;
typedef long long ll;
priority_queue,greater > q; //从小到大的队列
int n,a;
ll sum; //卡ll,int过不去
int main(void)
{
cin>>n;
for(int i=0;i>a;
q.push(a);
}
while(q.size()!=1) //合成一根结束
{
int t1=q.top(); //取第一个
q.pop();//记得弹出才能取下一个
int t2=q.top();//取第二个
q.pop();
int t3=t1+t2; //合成
sum+=t3; //sum记录总的消费
q.push(t3); //再把合成的插入
}
cout<