上次学习了一些STL的基本概念,那么今天煮波也是马不停蹄的找了几道例题来加强一下对这些容器的应用吧~(善良的煮波当然会给出详细代码的)
1-栈~
基础模拟:栈
这道题目就是最基础的栈的相关操作的模拟
代码直接放出(水个题)
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n;
while(cin>>n)
{
stack<int> stk;
string st;
while(n--)
{
cin>>st;
if(st=="push")
{
int x;
cin>>x;
stk.push(x);
}
else if(st=="pop")
{
if(!stk.empty())
stk.pop();
}
else if(st=="sum")
{
cout<<stk.size()<<endl;
}
else if(st=="out")
{
while(!stk.empty())
{
cout<<stk.top()<<endl;
stk.pop();
}
}
}
}
return 0;
}
2-栈的入门必刷题
有一个B<----(C)<----A的车站,列车从A开过来然后车站C是一个不能掉头的死胡同,意思就是到车站之后只能往B走了, A中列车的原始列车序列为:1 2 3 … N,B中存储列车的目标序列,问B中给出的列车目标序列是否可以将A中的原始序列通过中转站station实现。A中的数进station了,就不可以返回到A中。
首先分析问题,如果车站中有两节车厢那么只能在最外面的车厢出去之后里面的车厢才能继续出去,如果只有一节那么就可以出去,这明显是一个栈问题,题目问是否能按照目标序列将每一节车厢驶出,这样我们可以用一个指针依次指向目标序列,通过对栈中的栈顶来对指针所指的目标序列车厢进行比较,如果一样的话就让指针指向下一个元素,首先要判断目前的第i节车厢与目标序列是否相同,如果相同的话就直接让i++,j++就行了(直接让目前的这节车厢使出车站即可),如果不相同的话就把i存到栈中,然后在栈非空的条件下不断判断栈顶和指针所指的目标序列车厢是否相同,如果相同的话直接驶出(删除栈顶,j++)即可,最后可以通过判断栈是否为空来确定输出yes还是no;
代码如下:
#include <iostream>
#include<stack>
using namespace std;
int b[1010],n;
int main()
{
while(cin>>n&&n!=0)
{
while(1)
{
cin>>b[1];
if(b[1]==0) break;
for(int i=2;i<=n;i++)
{
cin>>b[i];
}
int i=1,j=1;
stack<int> s;
while(i<=n)
{
if(i==b[j])
{
i++;j++;
}
else
{
s.push(i++);
}
while(!s.empty()&&s.top()==b[j])
{
j++;
s.pop();
}
}
if(s.empty()) cout<<"Yes"<<endl;
else cout<<"No"<<endl;
}
cout<<endl;
}
return 0;
}
3-队列
队列入门必刷题:海港
对于所求问题--国籍有几种,可以用类似桶排序的思想,开一个数组,每一个角标代表一个国籍,对应的元素就是这个国籍的的人数,其次需要开一个结构体来储存每一个人的信息(主要就是到达的时间和国籍),然后再思考问题,对于每一艘船的前24小时之内,如果有船不在这时间范围内,就会剔除掉,而这艘船正好就是比较先到的船只,遵循先进先出原则,即队列的数据结构,所以可以再开一个队列,用来储存每一个人,具体实现思路如下:
首先读入n ,然后对每一个船只信息的时间和人数读入,然后对于每个人的国籍进行读入,让这个人的到达时间用这艘船的到达时间赋值,然后将这个人的结构体传入元素为结构体类型的队列中,然后进行判断,如果此时这个国家人数为0,就让ans++,然后让这个国家的人数++,然后就是删人操作,在队列非空的条件下如果此时输入的时间与队首人到达时间相差超过了24小时,则需要删掉这个队首,不过在删除之前的话首先要对这个国家的人数--,然后判断此时的国家人数如果==0的话就让ans--即可,由于时间是先后顺序所以使劲按相差不超过24小时直接break;节省时间,最后输出ans即可;
代码如下:
#include <bits/stdc++.h>
using namespace std;
int n,tt,kk,in[100010],ans=0;
struct person
{
int t,x;
}p;
queue<person> s;
int main()
{
cin>>n;
for(int i=0;i<n;i++)
{
cin>>tt>>kk;
for(int j=0;j<kk;j++)
{
cin>>p.x;
p.t=tt;
s.push(p);
if(in[p.x]==0) ans++;
in[p.x]++;
}
while(!s.empty())
{
if(tt-s.front().t>=86400)
{
p=s.front();
s.pop();
in[p.x]--;
if(in[p.x]==0) ans--;
}
else break;
}
cout<<ans<<endl;
}
return 0;
}
4-集合set:
这个就没什么好说的了,直接就是set的最基本的一些操作
#include<set>
#include<iostream>
#include<algorithm>
using namespace std;
set<int> se;
int main()
{
int n,m,x;
while(cin>>n>>m)
{
for(int i=0;i<n;i++)
{
cin>>x;
se.insert(x);
}
for(int i=0;i<m;i++)
{
cin>>x;
se.insert(x);
}
int sign=1;
for(auto it :se)
{
if(sign)
{
cout<<it;
sign=0;
}
else
{
cout<<' '<<it;
}
}
cout<<endl;
se.clear();
}
return 0;
}
5-字符串string(超超超好用!!!)
题目
首先这个题也是要求字符串和数字相联系,所以也要考虑映射map ;
由于题目要求所有的D-对为一组所以应该在双重循环时以这个范围为准,不能像冒泡排序法一样循环,而且判断完一组之后应该对map清空,因为题目中说了尽管字符对一样但是属于不同的D对,所以在判断完一组D对之后应该将map清空进行下一组D对的判断
具体思路如下:
首先创建一个char字符数组来存放当前的字符对,然后定义一个标记sign,然后开始双重循环,外层循环用于控制D对的值,内层循环用于控制字符对的起始位置然后对a[0]=s[j];a[1]=s[i+j];a[2]=’\0’;最后根据编制变量sign的值来输出结果即可;
代码如下:
#include<iostream>
#include<map>
using namespace std;
int main()
{
string s;
char a[3];
map<string,int> mp;
while(cin>>s)
{
if(s=="*") break;
bool sign=true;
for(int i=s.length()-1;i>=1;i--)
{
mp.clear();
for(int j=0;j<s.length()-i;j++)
{
a[0]=s[j];
a[1]=s[i+j];
a[2]='\0';
if(mp[a]==1)
{
sign=false;
break;
}
else
{
mp[a]=1;
}
}
if(!sign) break;
}
if(sign)
cout<<s<<" is surprising."<<endl;
else
cout<<s<<" is NOT surprising."<<endl;
}
return 0;
}
map的经典用法:
通过各个键值对进行快速的查找操作
#include<stdio.h>
#include<iostream>
#include<map>
using namespace std;
int main(void)
{
int n;
cin>>n;
map<string,int> m;
while(n--)
{
string s;
cin>>s;
m[s]++;
if(m[s]==1)
cout<<"OK"<<endl;
else
cout<<s<<m[s]-1<<endl;
}
return 0;
}
以上就是一些对于c++中的一些最基础的容器的入门的题目练习,以后煮波会在刷题过程中逐渐整理一些与这些基础算法和用法的相关题目,也会继续发布博客...(学长补药施压了).