栈
(本文为笔者个人学习笔记,如有不当之处恳请各位读者指正)
栈是限定仅在表头进行插入和删除操作的线性表,是一种符合"后进先出"(Last In First Out,LIFO)规则的数据结构,有PUSH和POP两种操作,其中PUSH把元素压入"栈顶",而POP从栈顶把元素"弹出".
例:
简译:有一个专门为了集合运算而设计的“集合栈”计算机。该机器有一个初始为空的栈,并且支持一下操作.
- PUSH: 将一个空集"{}"入栈。
- DUP: 把当前栈顶元素复制一份后再入栈。
- UNION: 出栈两个集合,然后把二者的交集入栈。
- INTERSECT: 出栈两个集合,然后把二者的交集入栈。
- ADD: 出栈两个集合,然后把先出栈的集合加入到后出栈的集合中,把结果入栈。
- UNION操作得到{{},{{}},{{{}}}},输出3.
- INTERSECT操作得到{{}},输出1.
- ADD操作得到{{},{{{}}}, {{},{{{}}}} },输出3.
#include<iostream>
#include<stack>
#include<set>
#include<map>
#include<vector>
#include<algorithm>
using namespace std;
typedef set<int> Set;
map<Set,int> IDcache; // 把集合映射到ID
vector<Set> Setcache; // 根据ID取集合
#define ALL(x) x.begin(),x.end() // 宏定义:用程序中传给ALL()的参数X调用begin和end方法,即用x.begin(),x.end()来替换程序中出现的ALL(x)
#define INS(x) inserter(x,x.begin())
// 查找给定集合的ID。
int ID(Set x){
if(IDcache.count(x)) // 集合x的ID存在
return IDcache[x];
else{ // 集合x的ID不存在
Setcache.push_back(x); // 添加到新集合中
return IDcache[x]=Setcache.size()-1; // 按照添加到Setcache中的顺序为集合x赋值ID,并返回
}
}
int main(){
int t,n;
string op;
cin>>t; // 测试组数
while(t--){
stack<int> s;
cin>>n; // 指令数
while(n--){
cin>>op;
if(op[0]=='P')
s.push(ID(Set())); // PUSH:空集"{}"入栈
else if(op[0]=='D')
s.push(s.top()); // DUP:把当前栈顶元素复制一份后再入栈
else{
Set x1=Setcache[s.top()];s.pop(); // 第一个集合出栈
Set x2=Setcache[s.top()];s.pop(); // 第二个集合出栈
Set x;
if(op[0]=='U')
// x1、x2取并集再插入到x中.使用宏定义后等价于
//set_union(x1.begin(),x1.end(),x2.begin(),x2.end(),inserter(x,x.begin()));
set_union(ALL(x1), ALL(x2), INS(x));
if(op[0] == 'I')
// x1、x2取交集再插入到x中.set_union和set_intersection是头文件algorithm下的
// 执行集合并、交运算的函数
set_intersection(ALL(x1), ALL(x2), INS(x));
if(op[0] == 'A'){
x = x2;
x.insert(ID(x1)); // 将先出栈集合x1插入到后出栈集合x2中后
}
s.push(ID(x)); // 操作结果入栈
}
cout<<Setcache[s.top()].size()<<"\n";
}
cout<<"***"<<endl;
}
return 0;
}
题目链接: The SetStack Computer - UVa12096
相关应用:中缀表达式转后缀表达式