栈、队列与优先队列

栈、队列与优先队列

新学了一下紫书上的三个例题(=。=自己完全不会编啊),
主要讲栈、队列与优先队列。

1.栈

栈是一种符合“后进先出”规则的数据结构,有PUSH和POP两种操作,其中PUSH把元素压如“栈顶”,而pop从栈顶把元素弹出。
头文件<stack>;
定义:stack<int> s 声明了一个栈,
栈的操作函数:
入栈s.push()
出栈s.pop()
取栈顶元素s.top()

相关题目:UVA12096-5.5-集合栈计算机
链接:
https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=835&page=show_problem&problem=3248
这个题就是各种栈操作,不过放入栈的是集合。
=。=集合套集合
题目分析:
首先是要学习两个函数:
(1).set_union (first, first+5, second, second+5, v.begin());
作用:将多个集合合并成没有交集的集合。
大概就是求两个集合的“并集减去交集”
函数元素:集合A首地址,尾地址
集合B首地址,尾地址
(2).set_intersection()
作用:实现求集合A,B交集。
函数元素:集合A首地址,尾地址
集合B首地址,尾地址
然后是整体这个题的思路:
一个很重要的地方就是给集合进行标记:

typedef set<int> Set //小技巧,减少需要输入的代码=。=
map<Set,int> IDcache;
vector<Set> Setchache;
int ID (Set x)
{
    if(IDcache.count(x))
        return IDcache[x];
    Setcache.push_back(x);
    return IDcache[x]=Setchache.size()-1;
}

这便是给集合进行标记的函数,主函数传入一个集合,首先判断这个集合是否标过了,通过IDcache.count(x)进行查找,如果已经被标记,返回这个集合的标记数字,如果没有,将这个集合加入vector容器,并加入一个标记,并返回这个标记。
代码通使用映射map使得每个集合都可以有对应的标记。

然后书上用了一个很好玩的东西,宏定义来减少重复代码(=。=我怎么就想不到呢)

#define ALL(x) x.begin(),x.end()
#define INS(x) inserter(x,x.begin()

这样就可以不用写长长的代码了。

然后是主函数

int main()  
{  
    int n;  
    cin>>n;  
    while(n--)  
    {  
        int m;  
        cin>>m;  
        for(int i=0;i<m;i++)  
        {  
            string op;  
            cin>>op;  
            if(op[0]=='P') s.push(ID(Set()));  
            else if(op[0]=='D') s.push(s.top());  
            else  
            {  
                Set x1=Setcache[s.top()];s.pop();  
                Set x2=Setcache[s.top()];s.pop();  
                Set x;  
                if(op[0]=='U') set_union(ALL(x1),ALL(x2),INS(x));  
                if(op[0]=='I') set_intersection(ALL(x1),ALL(x2),INS(x));  
                if(op[0]=='A') {x=x2;x.insert(ID(x1));}  
                s.push(ID(x));  
            }  
            cout<<Setcache[s.top()].size()<<endl;  
        }  
        cout<<"***"<<endl;  
    }  
    return 0;  
}  

主要就是熟悉栈的操作,可惜我现在还是迷迷糊糊的。=、=

2.队列与优先队列

队列是符合“先进先出”规则(就像食堂排队一样)的一种数据结构,
而优先队列有些特殊,不止是先进先出,而且还有优先级。
头文件:<queue>
队列的操作函数:

queue<int> q;
q.push(x);//加入队列
int t=q.front();//返回队首元素,但是不弹出队列
q.pop();//首元素弹出队列

在STL的库里面,还有对于优先队列的模板(大概是叫模板?)
声明方式:priority_queue<int> q
这是一个“越小的整数优先级越低的优先队列”。
由于出队元素并不是先进队的元素,所以取将要出队元素的办法由queue的front()变成了top()。
自定义类型也可以组成优先队列,但必须为每个元素定义一个优先级。这个优先级并需要一个确定的数字,只需要能比较大小就可以。
就像是C/C++里面的sort函数自定义一个排序方式一样。

priority_queue<int,vector<int>,cmp> pq
struct cmp
{
    bool operator() (const int a,const int b) const
    {
        return a%10>b%10 //a的优先级比b小时返回TRUE
    }
};

对于上面的那个Strut,我感觉又像是前面自己定义加法运算,依然不是很懂,有空补一蛤。

当然,对于常见的优先队列,STL提供了更为简单的定义方法。
越小的整数优先级越大的优先队列 可以写成

priority_queue<int,vector<int>,greater<int> > q;

注意最后两个> 符号不要写一起,以免被编译器认为是 “>>”运算符

相关题目:
UVA540-5.6-团体队列
链接:
https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=835&page=show_problem&problem=481
题目大意就是几个团体进行排队,新来排队的人如果发现前面有自己的队友,可以直接插到最后一个队友后面。
题目分析:
这个题用一个主队列加一个数组队列,主队列里面是插入团体,数组队列是每个队列代表一个团体,每当来一个人,如果主队列里面有队友(即数组队列里面对应团体不为空),那在数组队列对应团体里面加入这个人,如果没有队友,那在数组队列对应团体里面加入这个人,再将这个团体加入队列里面。
给出代码:
贴一位其他博主大大写的代码:
http://blog.csdn.net/a197p/article/details/43408927

UVA136-5.7-丑数(Ugly Number)
链接:
https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=835&page=show_problem&problem=72
求第1500个丑数,丑数即为不能被2,3,5以外的素整除的数(1也是丑数)。
题目分析:
算是优先队列的练习题了,用一个整数越小优先级越大的数存丑数,用一个map集合来存素数(利用集合的唯一性),利用count函数在集合里面查重,不重的话放到集合和队列里面,不断往队列里面放数取数就好了。
给出代码:
直接贴一下紫书上的代码好了(=。=作者大佬写的代码都好整洁)

#include<iostream>
#include<vector>
#include<queue>
#include<set>
using namespace std;
typedef long long LL;
const int coeff[3]= {2,3,5};
int main()
{
    priority_queue<LL,vector<LL>,greater<LL> > pq;
    set<LL> s;
    pq.push(1);
    s.insert(1);
    for(int i=1;; i++)
    {
        LL x=pq.top();
        pq.pop();
        if(i==1500)
        {
            cout<<"The 1500'th ugly number is "<<x<<".\n";
            break;
        }
        for(int j=0; j<3; j++)
        {
            LL x2=x*coeff[j];
            if(!s.count(x2))
            {
                s.insert(x2);
                pq.push(x2);
            }
        }
    }
    return 0;
}

最后再膜拜一下这个代码 0。0



总结:
栈和队列是两种比较相似的数据结构,一个符合先进后出,一个符合先进先出。在STL库里面都预有这两种结构,分别是stack和queue。这两种结构理解起来很简单,但是关键是如何用这两种结构,将其用到实际当中去,估计还需要以后的反复练习。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值