队列极值

这道数据结构题目要求实现队列的基本操作及查询最大值和最小值。通过三个栈来解决,一个用于正常入队和出队,另外两个分别记录当前队列中的最小值和最大值。当进行相应操作时,更新这两个辅助栈即可。输入包含多组数据,每组数据以正整数n开始,表示n次操作,操作包括入队、出队、查询最大值和最小值。输出对应的操作结果,队列为空时输出'EMPTY!'。
摘要由CSDN通过智能技术生成

题目来源

2015中北大学‘计蒜客’杯新生赛

问题描述

转眼间【HuJie】在灵隐寺待了将近半年,别说和日剧里的和尚似的泡到妹子结婚,就是连妹子的人影都见不着。好歹我们【HuJie】也是一表人才,英俊潇洒的,怎么能孤独终老呢?他才明白日剧里都是骗人的,还是回去好好的念书吧。 但是,【HuJie】偷偷出家的日子里已经旷了不少课了,所幸没有被学校查课给查出来,于是又偷偷溜回来上课了。但是实验室的【潘老师】可不会这么容易就放过贪玩的【HuJie】,他因为实验室的事情忙得不行,却到处找不着【HuJie】,这回【HuJie】自己溜回来了。于是【潘老师】对【HuJie】说:“这样吧,你做一道《数据结构》的队列题,要是做出来了,我就不追究你了。不过这次的数据量有点儿大,可要好好想想怎么做。”聪明的你能帮帮他吗?

输入描述

输入包含多组数据,每组数据以一个正整数n(1≤n≤5×〖10〗^5)开始,表示之后共有n次队列操作,之后n行每行包含一个操作。入队操作为”ENQUEUE x”,其中0≤x≤〖10〗^9表示将元素x入队;出队操作为”DEQUEUE”;询问操作为”MAX”或”MIN”,分别表示询问当前队列中的最大值或最小值。输入数据以0结束。

输出描述

对应每一组输入数据,第一行输出”Case #:”表示第#组数据,之后对每一次出队操作返回当前出队的元素,对每一次询问操作输出恰当的结果,若队列为空则输出”EMPTY!”,每次输出占一行。

输入样例

3
ENQUEUE 1
MAX
DEQUEUE
5
ENQUEUE 2
MAX
DEQUEUE
MIN
DEQUEUE
0

输出样例

Case 1:
1
1
Case 2:
2
2
EMPTY!
EMPTY!

分析

      其实这道题可以用三个栈来做。一个栈存储入栈的数据,一个栈维护最小值,一个栈维护最大值。上年没想到这种思路。下边的题解是半年前写的。

这道题考队列的入队,出队,取最大值,最小值操作。可以用c++ 的queue和multiset进行模拟。队列中可能存在重复元素,所以不能用set,队列出队时,multiset也删除出队的元素。一个值可能在队列出现多次,但每次只删除一个。下面说一下multiset怎么删除元素。

multiset<int> s      int x;     从队列s中删除x

multiset的删除操作:

1,删除某个迭代器上的元素。

    s.erase(s.find(x));  //只删除multiset中的一个值为x的元素

2.删除某段迭代器区间的元素。

3.删除键值等于某个值的所有元素,并返回删除元素的个数。

int num=s.erase(x);  //删除所有值为x的元素,num是删除元素的个数

这道题用的是操作1.

然后说一下取最小值,最大值操作:

multiset里的元素是从小到大排列的,x=*s.begin();就可以拿到最小值。  但是s.end()并不是最后一个元素的迭代器位置,而是最后一个位置的后一个位置。 *(--s.end())  就拿到最大值了
           


代码

#include<algorithm>
#include <iostream>
#include<cstring>
#include<set>
#include <cstdio>
#include<queue>
using namespace std;
typedef long long ll;
int n;
char c[10];
int main(){
    int cnt=1;
    while(scanf("%d",&n)&&n){
        queue<int> q;
        multiset<int> s;
        printf("Case %d:\n",cnt++);
        for(int i=0,x;i<n;i++){
            scanf("\n%s",c);
            if(c[0]=='E'){      //入队
                scanf("%d",&x);
                q.push(x);
                s.insert(x);
            }else if(c[0]=='D'){   //出队
                if(!q.empty()){
                    x=q.front();
                    q.pop();
                    s.erase(s.find(x));
                    printf("%d\n",x);
                }else{
                    printf("EMPTY!\n");
                }
            }else if(c[1]=='I'){   //取最小值
                if(!q.empty()){
                    x=*s.begin();
                    printf("%d\n",x);
                }else{
                    printf("EMPTY!\n");
                }
            }else if(c[1]=='A'){ // 取最大值
                if(!q.empty()){
                    // multiset<int>::iterator it=s.end();
                    //it--;
                    // printf("%d\n",*it);
                    printf("%d\n",*(--s.end()));
                }else{
                    printf("EMPTY!\n");
                }
            }
        }
    }
    return 0;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值