您的位置:首页 > 其它

STL 栈和队列(5重要)

2020-02-02 19:46 225 查看

STL 栈和队列

前几篇写的都是一些最基础的一些算法,而这篇介绍一些很重要的东西。
STL的代码从广义上讲分为三类:algorithm(算法)、container(容器)和iterator(迭代器)。
STL(Standard Template Library),即标准模板库,是一个高效的C++程序库。它被容纳于C++标准程序库(C++Standard Library)中,该库包含了诸多在计算机科学领域里 所常用的基本数据结构和基本算法。 我们常用到STL中的vector不定数组) set(集合) string(字符 串)map(字典)全排列next permutation。
STL 栈和队列超级重要,下面这些基本操作得熟练。
下面简绍一些容器的最最基本操作,更多骚操作,还需读者自己百度:
1:vector
vector即是一个不定长度的数组,所谓不定长度,就是我们 往里面扔多少元素,他就有多大,它的访问跟我们原先使用 的数组也一样

vector <int > ve ;//定义一个int型数组ve
ve . erase ( ve . begin ()+1); //删除的是第一个元素(下标 从0 始)
ve . insert ( ve . begin ()+1 ,1); //把删除的再加进去
ve . erase ( ve . begin ()+1 , ve . begin ()+4); //删 除 的 第1,2,3 的元素共三个元素
cout < < ve . size () < < endl ;//看一下数组的大小
ve . clear (); //清空数组

顺便先简单的看一个迭代器的使用吧!
迭代器提供对一个容器中的对象的访问方法,并且定义了容器中对象的范围。迭代器就如同一个指针。事实上,C++的指针也是一种迭代器。但是,迭代器不仅仅是指针,因此你不能认为他们一定具有地址值。例如,一个数组索引,也可以认为是一种迭代器。

#include<iostream>
#include<vector>
#include<string>
#include<algorithm>
using namespace std;
int main() {
vector<char> v;
v.push_back('a');
v.push_back('b');
v.push_back('c');
v.push_back('d');
for (int i = 0; i < 4; i++)//输出容器内的元素
cout << "v[" << i << "]==" << v[i] << endl;
cout << "第三个元素是" << v[2] << endl;
vector<char>::iterator p = v.begin();//定义迭代器p初始化为容器起始位置
p++;//将迭代器移向下一个位置
cout << *p << endl;
p++;
cout << *p << endl;
p--;//移向上一个位置
cout << *(p + 2) << endl;//输出第四个元素

int array[10];
array[5] = 100;
int *ip = find(array, array + 10, 100);//find的使用(第一个元素位置,最后一个元素位置,待定位的值)
if (ip == array + 10)
cout << "not found" << endl;
else
cout << *ip << "found" << endl;

vector<int>::iterator q;
vector<int> s(10);
int n = 0;
for (q =s.begin(); q != s.end(); q++)//使用begin和end来循环
*q = n++;
for (q = s.begin(); q != s.end(); q++)
cout << *q << " ";
cout << endl;
return 0;
}
//运行结果:
//v[0]==a
//v[1]==b
//v[2]==c
//v[3]==d
//第三个元素是c
//b
//c
//d
//100found
//0 1 2 3 4 5 6 7 8 9

2:set
set即是一个集合,这个集合不允许相同的元素存在,所 以set中的元素是唯一 的 。
例如:我们把2,3,4,7,4都扔进set里,那么set里面就会 有2,3,4,7这四个元素

set <int > st ;//定义一个int型set
st . insert () //在集合中插入元素
st . begin () //返回指向第一个元素的迭代器
st . end () //返回指向朑 后一个元素之后的迭代器,不是 朅 后一个元素
st . clear () //清除所有元素
st . count () //返回bool型,有返回1,无返回0
st . empty () //如果集合为空,返回true
st . erase () //删除集合中的元素
st . find () //返回一个指向被查找到元素的迭代器,如果 没找到则返回end()
st . size () //集合中元素的数目

一个简单板子题:
{A} + {B} HDU - 1412

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

int main()
{
set<int> s;
int a,n,m;
while(~scanf("%d %d",&n,&m))
{
s.clear();
set<int>::iterator it;
for(int i=0;i<n;i++)
{
scanf("%d",&a);
s.insert(a);
}

for(int i=0;i<m;i++)
{
scanf("%d",&a);
s.insert(a);
}

it =s.begin();
cout<<*it;
it++;
for(it;it!=s.end();it++)
cout<<" "<<*it;
printf("\n");

}
return 0;
}

相关题目:
不重复数字 HYSBZ - 2761
3.string
string是一个很方便使用的字符串,跟vector差不多,不定长 度

string s = " cloudy_happy " ;//定义一个字符串s并初 始化
s += " is zyc " ; //在s的后面加上这一串
字符,但不能-
cout < <s < < endl ; //输出s
//string也可以用> < ==来进行字典序的比较,返回0 or 1
s . clear (); //清空s
cin > > s ; //cin输入

4:map
map即是一个字典,是 种映射即对应关系,map的使用很方便例如:我们们个人的学号对应自己的名字,就可以用map来 存

map < string , ll > mp ;//定 义 一 个 名 为mp的map, 前 面 的string是它的key,后者是value
mp [ " clody_happy " ] = 311709000429 //cloudyhappy对 应3117的映射
mp . clear (); //清空mp
cout < < mp . size (); //mp的大小
mp . empty (); //判断mp是否为空
mp . count ( key ); //判断key是否存在

日常来一个板子题:
Let the Balloon Rise HDU - 1004

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
int n;
map<string,int> mp;
while(scanf("%d",&n)&&n)
{
mp.clear();
string s;
for(int i=0;i<n;i++)
{
cin>>s;
mp[s]++;
}
map<string,int>::iterator it;
int z=0;
for(it=mp.begin();it!=mp.end();it++)
{
if(it->second>z)//map第二个值大于z
{
z=it->second;
s=it->first;
}
}
cout<<s<<endl;
}
return 0;
}

相关题目:
水果 HDU - 1263(真的是难)
5:全排列(用到的时候比较少,但仍需要好好学,以防万一)
全排列有两个函数next permutation(全排列的下一个排 列)和prev permutation(字典序的上一个排列)不过要注意它 的复杂度是O(n!)

char s [10] = "012" ;
//按字典序输出012的全排列
do{
printf ( "%s\n",s );
} while ( next_permutation (s , s + 3));
//pre_vpermutation的使用同理

char s[10] = "210" ;//想想用这个012还能排吗?
//按字典序输出210的全排列
do{
printf ("%s\n",s);
} while ( prev_permutation (s , s + 3));

日常来一个板子题:

排列2 HDU - 1716
这个题不难,但是输出格式真的是坑的要死,PE了我5次才对。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

int main()
{
int a[5];
int tmp=0;
while(cin>>a[0]>>a[1]>>a[2]>>a[3])
{

if(a[0]==0&&a[1]==0&&a[2]==0&&a[3]==0)
break;
if(tmp)
cout<<endl;
tmp=1;
int flag=1;
int tt=-1;
do
{
if(a[0]!=0)
{
if(flag)
{
cout<<a[0]<<a[1]<<a[2]<<a[3];
flag=0;
}
else if(tt==a[0])
cout<<" "<<a[0]<<a[1]<<a[2]<<a[3];
else
cout<<endl<<a[0]<<a[1]<<a[2]<<a[3];
tt=a[0];
}
}while(next_permutation(a,a+4));
cout<<endl;
}
return 0;
}

相关题目:
Ignatius and the Princess II HDU - 1027 (还是有个坑)

#include<bits/stdc++.h>
using namespace std;
int main()
{
int n,m;

while(~scanf("%d %d",&n,&m))
{
int a[10010];
int k=0;
for(int i=0;i<=n;i++)
a[i]=i+1;
do{
k++;
if(m==k)
break;
}while(next_permutation(a,a+n));
for(int i=0;i<n;i++)
{
if(i!=n-1)
printf("%d ",a[i]);
else
printf("%d\n",a[n-1]);
}

}
return 0;
}

6:栈
栈和队列是一 种特殊的线性表,其区别在于栈是先进后出像
一个瓶子,而队列是先进先出像排队。

stack <int > s ;//定义一个int型栈s
s . push (2); //把2从栈顶压入栈
s . top (); //栈顶元素
s . pop (); //弹出栈顶元素
s . empty (); //判断栈是否为空
s . size (); //栈的大小

俩个经典的例题:
Rails POJ - 1363

//#include<bits/stdc++.h>
#include<stdio.h>
#include<stack>
#include<cstring>
using namespace std;
typedef long long ll;
int a[1010];
int main()
{
int n;
while(~scanf("%d",&n)&&n)
{
while(1)
{
scanf("%d",&a[0]);
if(!a[0])
{
printf("\n");
break;
}

for(int i=1;i<n;i++)
scanf("%d",&a[i]);
stack<int> s;
int pos=0;
for(int i=1;i<=n;i++)
{
s.push(i);
while(!s.empty()&&s.top()==a[pos])
{
s.pop();
pos++;
}
}
if(s.empty())
printf("Yes\n");
else
printf("No\n");
}

}
return 0;
}

还有这个:
Train Problem I HDU - 1022

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

int main()
{
int n;
char aa[250];
char bb[250];
int flag[250];
while(cin>>n>>aa>>bb)
{

stack<char> st;
memset(flag,0,sizeof flag);
int j=0,k=0;
for(int i=0;i<n;i++)
{
st.push(aa[i]);
flag[k++]=0;
//while(st.top()==bb[j]&&!st.empty())   读者可以考虑为什么这样写就错了,一个很有意思的BUG(不是短路哦)
while(!st.empty()&&st.top()==bb[j])
{
flag[k++]=1;
st.pop();
j++;
}

}

if(st.empty())
{
printf("Yes.\n");
for(int i=0;i<k;i++)
{
if(flag[i]==0)
printf("in\n");
else
printf("out\n");
}
printf("FINISH\n");
}
else
{
printf("No.\n");
printf("FINISH\n");
}
}

return 0;
}

7.队列

queue <int > q ;//定义一个int型队列q
q . push (1); //把1推入队列
q . front (); //队首元素
q . pop (); //弹出队首元素
q . empty (); //判断队是否为空
q . size (); //队列的大小

这是一个优先队列的板子题,读者可以去学习学习优先队列,还是蛮有用的。(下一篇我还是自己介绍吧!)
Windows Message Queue HDU - 1509

#include<bits/stdc++.h>
using namespace std;

struct node
{
char str[100];
int s1;
int s2;
int cnt;
friend bool operator<(node a,node b)
{
if(a.s2!=b.s2)
return a.s2>b.s2;
else
return a.cnt>b.cnt;
}
}NODE;
int main()
{
int k=0;
char op[5];
priority_queue<node> Q;
while(scanf("%s", op) != EOF)
{
if(op[0]=='G')
{
if(Q.empty())
{
printf("EMPTY QUEUE!\n");
continue;
}
else
{
NODE=Q.top();
Q.pop();
printf("%s %d\n", NODE.str, NODE.s1);
}
}
else if(op[0]=='P')
{
scanf("%s%d%d", NODE.str, &NODE.s1, &NODE.s2);
NODE.cnt=k++;
Q.push(NODE);
}
}

return 0;
}

再来一个队列和栈结合的简单题:
ACboy needs your help again! HDU - 1702

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int N;
int n;
string a;
string b;
int m;
queue<int> q;
stack<int> s;

int main()
{
ios::sync_with_stdio(false);
cin>>N;
while(N--)
{
while (!q.empty())
q.pop();
while (!s.empty())
s.pop();
cin>>n>>a;
if(a=="FIFO")//队列
{
for(int i=0;i<n;i++)
{
cin>>b;
if(b=="IN")
{
cin>>m;
q.push(m);
}

if(b=="OUT")
{
if(!q.empty())
{
cout<<q.front()<<endl;
q.pop();
}
else
cout<<"None"<<endl;
}
}
}
else        //栈
{
for(int i=0;i<n;i++)
{
cin>>b;
if(b=="IN")
{
cin>>m;
s.push(m);
}
if(b=="OUT")
{
if(!s.empty())
{
cout<<s.top()<<endl;
s.pop();
}
else
cout<<"None"<<endl;

}
}
}
}
return 0;
}

学完这些还有二个难度较大的题目,读者可以选做:
水果 HDU - 1263
Andy’s First Dictionary UVA - 10815

  • 点赞
  • 收藏
  • 分享
  • 文章举报
〆℡小短腿走快点ゝ 发布了30 篇原创文章 · 获赞 1 · 访问量 1423 私信 关注
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: