1. 程式人生 > >算法入門經典-第五章 例題5-6 團體隊列

算法入門經典-第五章 例題5-6 團體隊列

com ont func sam 移除 inpu 輸入 類型 隊列

題目背景

隊列和優先級隊列是大多數計算機科學家都知道的數據結構。但是團隊隊列卻不被人熟知,盡管在生活中經常出現。比如,午餐時間的食堂門口的隊列就是一個團隊隊列。在一個團隊隊列中,每個元素屬於一個團隊。如果一個元素進入一個隊列,它首先從頭到尾地搜尋這個隊列——檢查是否它的隊友(在同一個團隊稱之為隊友)也在這個隊列裏。如果有,它就排在它隊友的後面(:-D就是插隊咯~~)。如果沒有,它就排在整個隊列的最後,成為新的最後一名(/(ㄒoㄒ)/~真是不幸)。在普通隊列中出隊是這樣的:元素從頭到尾的被處理,按他們出現在團隊隊列裏的順序。你的任務是寫一個程序模擬這樣一個團隊隊列。

輸入

輸入文件會包含一個或多個測試樣例。每一個測試樣例由代表團隊數量的t(1<=t<=1000)開始。然後t只團隊描述如下,每一個團隊由一個表示元素個數的數字,以及每個元素組成。元素屬於整型,並且範圍在0到999999(一百萬減一)之間。一個團隊可能有多達1000個元素。最後,指令列表如下。有三種不同的指令:ENQUEUE x——x進入團隊隊列。DEQUEUE x——處理第一個元素並將其移除STOP——結束一個測試樣例。當t是0時,輸入終止。警告:一個測試樣例可能多達200000(/(ㄒoㄒ)/~~二十萬)條指令,所以團隊隊列的實現應該是有效率的:入隊和出隊都應該花費常數時間。

輸出

對應每個測試樣例,首先輸出一行“Scenario #k”,其中k表示第幾次測試。然後,每一個“DEQUEUE”指令打印包含出隊的元素(單獨占一行)。打印一空行在每一個測試樣例之後,即使是最後一個測試樣例。
例如:
Sample Input

2
3 101 102 103
3 201 202 203
ENQUEUE 101
ENQUEUE 201
ENQUEUE
102
ENQUEUE 202
ENQUEUE 103
ENQUEUE
203
DEQUEUE
DEQUEUE
DEQUEUE
DEQUEUE
DEQUEUE
DEQUEUE
STOP
2
5
259001 259002 259003 259004 259005
6 260001 260002 260003 260004 260005
260006
ENQUEUE 259001
ENQUEUE 260001
ENQUEUE 259002
ENQUEUE
259003
ENQUEUE 259004
ENQUEUE 259005
DEQUEUE
DEQUEUE
ENQUEUE
260002
ENQUEUE
260003
DEQUEUE
DEQUEUE
DEQUEUE
DEQUEUE
STOP
0

Sample Output

Scenario
#1
101
102
103
201
202
203

Scenario
#2
259001
259002
259003
259004
259005
260001

分析

題目明確告訴了我們使用隊列。使用一個隊列排列團隊;再使用一個隊列排列元素。題目中說了出隊入隊只能花費常數時間,所以要在元素和團隊之間建立映射關系而不能簡單地使用數組存下元素。

#include<cstdio>  
#include<queue>  
#include<map>  
using namespace std;  
const int maxt = 1000 + 10;  
int main()  
{  
    int t, kase = 0;  
    while(scanf("%d", &t) == 1 && t) {  
        printf("Scenario #%d\n", ++kase);  
  
        map<int , int> team;//映射作用是編號x對應它的隊伍i  
        for(int i = 0; i < t; i++) {  
            int n,x;  
            scanf("%d", &n);  
            while(n--) { scanf("%d", &x); team[x] = i;}  
        }  
  
        queue<int> q, q2[maxt];  
        //兩個隊列是本題的核心  
        //q存放的是隊伍,q2存放的是按增序排列的所有的隊伍以及隊伍下的編號  
        //即q存放團隊整體隊列,例{3,1,2}  
        //q2存放團隊隊列,例{103,101,102},{201},{301,303}  
        for(;;) {  
        int x;  
        char cmd[10];  
        scanf("%s", cmd);  
        if(cmd[0] == ‘S‘) break;//遇到STOP停止  
        else if(cmd[0] == ‘D‘){  
            int t = q.front();//用變量t表示團隊整體隊列的隊首  
            printf("%d\n",q2[t].front()); q2[t].pop();//輸出這個隊首隊伍的第一個人,然後把該人出隊  
            if(q2[t].empty()) q.pop();//如果該隊伍在整個隊列中只有一個人,則q的隊首出隊,即該隊伍出隊  
        }else if(cmd[0] == ‘E‘){  
            scanf("%d", &x);  
            int t = team[x];//通過map找出x的隊列序號  
            if(q2[t].empty()) q.push(t);//如果該隊還沒有人排在隊中,則該隊列插入隊尾  
            q2[t].push(x);//把該隊伍的人插入到q2的該隊中  
            }  
        }  
        printf("\n");  
    }  
    return 0;  
}

  

push()會將一個元素置入queue中。

  • front()會返回queue內的第一個元素(也就是第一個被置入的元素)。
  • back()會返回queue中最後一個元素(也就是最後被插入的元素)。
  • top()取隊首元素(但不刪除)。
  • pop()會從queue中移除一個元素。
  • 註意:pop()雖然會移除下一個元素,但是並不返回它,front()和back()返回下一個元素但並不移除該元素。

另:

優先隊列也定義在頭文件中,用"priority_quene pq"來聲明。(越小的整數優先級越低)

由於出隊的元素並不是最先進隊的元素,出隊的方法由front()變為了top().

越小的整數優先級越大的定義方式 "priority_queue<int,vector,greater > pq"

自定義類型也可以組成優先級隊列,但必須為每個元素定義一個優先級。

eg. 實現 “個位數的的整數優先級反而小” ,可以定義一個結構體cmp,重載“()” 運算符,然後用“priority_queue<int,vector,cmp> pq"的方式定義。

下面是cmp的定義

struct cmp{

    bool operator() (const int a, const int b)const{                  //a的優先級比b小時返回true

            return a%10>b%10;

       }

}

算法入門經典-第五章 例題5-6 團體隊列