1. 程式人生 > 其它 >棧和佇列的基本操作

棧和佇列的基本操作

一.前言:

    1.棧是一種先進後出結構的資料結構,棧加入元素是從棧頂加入的,刪除元素也是從棧頂刪除的;

    2.佇列是一種先進先出的資料結構,佇列加入元素是從隊尾加入的,刪除元素是從隊首刪除的;

二.習題練習

(A)

現在有n個元素分別是1,2,3,...,n,我們想知道通過一個棧,在n次push/pop後,出棧序列可能是什麼樣的。例如n是5,那麼入棧次序就是1,2,3,4,5,如果我們希望出棧次序同樣是1,2,3,4,5,那隻要每push一個數,就立即pop一個數。如果我們希望出棧次序是3,2,4,5,1,那麼我們先讓1,2,3入棧,然後pop出來3和2,接著4入棧後馬上pop,再就是5入棧後馬上pop,最後再把棧裡的1pop出。再例如,如果我們希望出棧次序是5,4,1,2,3,這是辦不到的,如果要讓5最先出棧,那麼出棧次序只可能是5,4,3,2,1

input:

輸入由多塊輸入構成,每塊的第一行是n,(1≤n≤1000),接著是多組測試資料,每組一行,每行由n個1到n的整陣列成,直到某一行第一個數是0表示此輸入塊結束,然後是下一塊資料。
當某一塊的第一行的n是0的時候結束所有輸入

output:

對每組資料,只要輸出Yes或No,Yes表示能產生那樣的出棧序列,No表示不能。 輸入塊與輸入塊之間要多輸出一個空行分隔。注意對於最後一個n為0的輸入塊不要多輸出空行。

sample input:

5

1 2 3 4 5

5 4 1 2 3

0

6

6 5 4 3 2 1

0

0

sample output:

Yes

No

Yes

題解:

#include "
stdio.h" int b[10100]; int a[10100],n,top,top1,m,j; int judge(){ for(j = 1;j <= n;j++){ a[++top] = j; while(top >= 1 && a[top] == b[top1]) //邊存入棧,邊匹配,匹配上了則執行pop操作 top--,top1++; } return top > 0; } int main() { while(1){ scanf(
"%d",&n); if(n == 0) break; while(1){ top = 0; top1 = 1; scanf("%d",&m); if(m == 0) break;//輸入每行第一個,如果為0則結束輸入 b[1] = m; for(j = 2;j <= n;j++) scanf("%d",&b[j]); if(judge()) printf("No\n"); else printf("Yes\n"); } printf("\n"); } return 0; }

(B)

定義一個二維陣列

int maze[5][5] = {


0, 1, 0, 0, 0,


0, 1, 0, 1, 0,


0, 0, 0, 0, 0,


0, 1, 1, 1, 0,


0, 0, 0, 1, 0,


};

它表示一個迷宮,其中的1表示牆壁,0表示可以走的路,只能橫著走或豎著走,不能斜著走,要求程式設計序找出從左上角到右下角的最短路線。

input:

一個5 × 5的二維陣列,表示一個迷宮。資料保證有唯一解。

output:

左上角到右下角的最短路徑,格式如樣例所示。

sample input:

0 1 0 0 0

0 1 0 1 0

0 0 0 0 0

0 1 1 1 0

0 0 0 1 0

sample output:

(0, 0)

(1, 0)

(2, 0)

(2, 1)

(2, 2)

(2, 3)

(2, 4)

(3, 4)

(4, 4)

題解:

#include "bits/stdc++.h"
using namespace std;
int mp[10][10];
struct node{
    int x,y;
    int step;
    int x1[10],y1[10];
};
int mv[4][2] ={{-1,0},{1,0},{0,-1},{0,1}};
queue <node> q;
node u,v,w;
int book[10][10];
int main()
{
    for(int i = 0;i < 5;i++)//初始化地圖
        for(int j = 0;j < 5;j++)
            cin >> mp[i][j];
    u.x = 0;
    u.y = 0;
    book[u.x][u.y] = 1;
    q.push(u);
    while(!q.empty()){
        v = q.front();//從隊首取出一個節點進行廣搜
        q.pop();//出隊
        if(v.x == 4 && v.y == 4){
            for(int i = 0;i < v.step;i++)
                cout << "(" << v.x1[i] << ", " << v.y1[i] << ")" << endl;//列印最短路徑
            cout << "(" << 4 << ", " << 4 << ")" << endl;//直接列印終點
            break;
        }
        for(int i = 0;i < 4;i++){
            w.x = v.x + mv[i][0];
            w.y = v.y + mv[i][1];
            w.step = v.step + 1;
            if(w.x > 4 || w.x < 0 || w.y > 4 || w.y < 0)
                continue;//如果超出地圖,則進行下一次嘗試
            if(book[w.x][w.y] == 1 || mp[w.x][w.y] == 1)
                continue;//如果這條路已經走過,或者這條路不能走,則進行下一次嘗試
            book[w.x][w.y] = 1;//標記這條路已經走過
            w.x1[v.step] = v.x;//儲存本次路徑
            w.y1[v.step] = v.y;//儲存本次路徑
            q.push(w);//儲存整條路徑
        }
    }
    return 0;
}

(C)

You are given a string consisting of parentheses( )and[ ]. A string of this type is said to be correct:

if it is the empty string

ifAandBare correct,ABis correct,

ifAis correct, (A) and [A] is correct.

Write a program that takes a sequence of strings of this type and check their correctness. Your program can assume that the maximum string length is128.

Input

The first line contains the number of test casesn. Each of the nextnlines contains the string of parentheses( )and[ ].

Output

For each test case print in a separate line "Yes" if the expression is correct or "No" otherwise.

Example 1

Input example #1

3

([])

(([()])))

([()[]()])()

Output example #1

Yes

No

Yes

題解:

#include "stdio.h"
#include "string.h"
int main()
{
    char ans[10010];
    char tt[10010];
    int n;
    scanf("%d",&n);
    getchar();//把換行接掉,避免影響到字串輸入
    for(int i = 0; i < n; i++){
        gets(tt);
        int j;
        for(j = 0;j < strlen(tt);j++)
            if(tt[j] != ' ')
                break;
        if(j == strlen(tt)){//如果全是空格,則輸出Yes
            printf("Yes\n");
            continue;
        }
        int top = 0;
        for(int i = 0; i < strlen(tt); i++){//進行括號匹配
            if(top == 0)
                ans[++top] = tt[i];
            else if(ans[top] == '(' && tt[i] == ')')
                top--;
            else if(ans[top] == '[' && tt[i] == ']')
                top--;
            else if(tt[i] != ' ')
                ans[++top] = tt[i];
        }
        if(top > 0)//如果沒有匹配完畢,則輸出NO
            printf("No\n");
        else 
            printf("Yes\n");
    }    
    return 0;
}

(D)

歡迎大家加入ACM!
要深入的學習ACM的相關知識,首先就必須學會一門程式語言,推薦C/C++。
不過對於初學者,因為沒編過多少程式碼,經常出現變異錯誤,其實就是語法錯誤。
現在要你檢查一段程式碼的語法是否否正確。
為了簡化問題,我們只檢查 (、)、{、} 括號是否匹配了,並且在輸入的程式碼中不包含字元的'(',')','{','}'。
其他語法錯誤不檢查,如 "#include <stdio.h","2 = x",是錯誤的,但是不檢查。

Input

有多組測試資料,每組測試資料有一段程式碼,該段程式碼可能在有多行。
每段程式碼以Ctrl+Z結束。
處理到檔案結束。

Output

每組測試資料輸出一行。
如果這段程式碼括號匹配了,輸出 Right ,否則輸出 Wrong。

Sample Input

#include <stdio.h
int main(){
int a b;
while (scanf("%d%d", &a, &b) != EOF) {
printf("%d\n", a + b);
}
}
Ctrl+Z
int main(){
int a, b;
while (scanf("%d%d", &a, &b) != EOF) {
printf("%d\n", a + b);

}
Ctrl+Z

Sample Output

Right
Wrong

題解:

#include "stdio.h"
#include "string.h"
char str[1010];
char stk[10010];
int top;
int main()
{
    top = 0;
    int flag = 0;
    while(scanf("%s",str) != EOF){
        if(strcmp(str,"Ctrl+Z") == 0)//進行匹配
            if(top == 0 && !flag){//如果已經匹配完成了,並且成功了
                flag = 0;
                printf("Right\n");
                continue;
            }
            else {
                flag = 0;
                printf("Wrong\n");
                top = 0;
                continue;
            }

            for(int i = 0;i < strlen(str);i++)//遍歷整個字串,進行儲存和匹配
                if(str[i] == '(')
                    stk[++top] = '(';
                else if(str[i] == '{')
                    stk[++top] = '{';
                else if(str[i] == ')' && top == 0 || str[i] == ')' && stk[top] != '(')
                    {   flag = 1;break;}
                else if(str[i] == ')' && stk[top] == '(')
                    top--;
                else if(str[i] == '}' && top == 0 || str[i] == '}' && stk[top] != '{')
                    {flag = 1;break;}
                else if(str[i] == '}' && stk[top] == '{')
                    top--;
    }
    return 0;
}

(E)

宇神完成了棧的實驗要求後,他又很是開心,剛要出去五排,菌菌子突然問道老師讓做的佇列的那個實驗你寫完了麼,宇神頓時大呼悲哉。。。。他給忘記了,怎麼辦。。明天就要上交實驗報告了,你能幫他搞定麼???

你需要完成三種操作1.enqueuex,將元素x插入隊尾。2.dequeue,若佇列非空,則刪去隊頭元素,並輸出該元素。3.query,從隊頭開始刪除所有元素,並輸出。

Input

本題有多組測試資料,每組資料首先輸入一個T,接下來T行是T種對佇列的操作。 (0< T < 100,0< x <= 500)

Output

每次執行dequeue操作時刪除隊頭元素輸出並換行,如果佇列為空輸出“thisisempty!”並換行。

每次執行query操作時刪除所有元素佇列內所有元素並輸出,每個元素佔一行,如果棧為空輸出“thisisempty!”並換行。

每組資料後有一個空行。

Sample Input

10

enqueue 1

enqueue 2

enqueue 3

enqueue 4

query

dequeue

enqueue 1

dequeue

query

dequeue

Sample Output

1

2

3

4

this is empty!

1

this is empty!

this is empty!

題解:

#include "bits/stdc++.h"
using namespace std;
int main()
{
    char s[1100];
    int que[1100];
    int x;
    int n;
    while(cin >> n){
        int head = 0;
        int tail = 0;
        while(n--){
            cin >> s;
            if(strcmp(s,"enqueue") == 0){//匹配入隊操作
                cin >> x;
                que[++tail] = x;
            }
            else{
                if(head == tail)//匹配出隊操作
                    cout << "this is empty!" << endl;
                else if(strcmp(s,"query") == 0){
                    while(head < tail)
                        cout << que[++head] << endl;
                }
                else if(strcmp(s,"dequeue") == 0)
                    cout << que[++head] << endl;
            }
        }
        printf("\n");
    }
    return 0;
}

(F)

冰冰子最近新學習了佇列和棧兩種重要的資料結構,他知道它們具有push 和pop操作。

而冰冰子現在想同時研究棧和佇列,於是,他開始了一個實驗。

現在,假設佇列和棧都是空的。給定一系列push k和pop操作之後,冰冰子想知道佇列和棧中分別存的數字。若佇列或棧已經空了,仍然接收到pop操作,則輸出error。

Input

第一行為m,表示有m組測試輸入,m<100。
每組第一行為n,表示下列有n行push k或pop操作。(n<150)
接下來n行,每行是push k或者pop,其中k是一個整數。
(輸入保證同時在佇列或棧中的數不會超過100個)

Output

對每組測試資料輸出兩行,第一行是佇列情況,若在佇列空時收到pop操作,則輸出error。其餘情況將佇列按照對頭至隊尾順序輸出佇列中所有元素,中間用空格隔開。第二行是棧的情況,若在棧空時收到pop操作,則輸出error。其餘情況下按照棧底至棧頂的順序輸出棧中所有元素。

Sample Input

2

4

push 1

push 3

pop

push 5

1

pop

Sample Output

3 5

1 5

error

error

題解:

#include "stdio.h"
#include "string.h"
char op[100];
int que[1100];
int stk[1100];
int top,head,tail,flag1,flag2;
int n,m,x;
int main()
{
    scanf("%d",&m);
    while(m--){
        scanf("%d",&n);
        top = head = tail = flag1 = flag2 = 0;
        while(n--){
                scanf("%s",op);
                if(op[1] == 'o' ){//匹配對應的操作
                    if(head == tail) flag1 = 1;//如果佇列為空執行pop操作
                    else head++;
                    if(top == 0) flag2 = 1;//如果棧為空執行pop操作
                    else top--;
                }
                if(op[1] == 'u'){
                    scanf("%d",&x);
                    que[++tail] = x;
                    stk[++top] = x;
                }
            }
        if(flag1) printf("error\n");//如果執行過非法操作,則輸出error
        else{
            while(head < tail)//打印出佇列全部元素
                printf("%d ",que[++head]);
            printf("\n");
        }
        if(flag2) printf("error\n");//如果執行過非法操作,則輸出error
        else{
            int t = 0;
            while(t < top)//列印棧區全部元素
                printf("%d ",stk[++t]);
            printf("\n");
        }
    }
    return 0;
}

(G)

給出一個由1到n組成的無序數列,如果我們把這個序列看成是數字1~n出棧的順序,並且入棧順序是1, 2, 3, ..., n,請問操作時,棧內最多能有多少個元素?

Input

輸入有多組資料。

每組資料的第一行為一個整數n代表由1到n的序列。 1<= n <=100。

第二行為n個用空格隔開的整數,範圍是[1,n]。

Output

若此序列能由進棧,出棧得到,輸出所使用的最小棧容,否則輸出-1

Sample Input

5

1 2 3 4 5

4

3 2 1 4

6

6 5 4 1 3 2

Sample Output

1

3

-1

題解:

#include "bits/stdc++.h"
int stk[110];
int a[110];
int top;
using namespace std;
int main()
{
    int n;
    while(cin >> n){
        int top1 = 0;
        top = 1;
        int ans = 0;//記錄最大個數
        for(int i = 1;i <= n;i++)
            scanf("%d",&a[i]);
        for(int i = 1;i <= n;i++){
            stk[++top1] = i;//存入棧區
            ans = ans > top1 ? ans : top1;//進行最大匹配
            while(stk[top1] == a[top] && top1 > 0){
                top1--;
                top++;
            }
        }
        if(top1 != 0)
            cout << -1 << endl;
        else 
            cout << ans << endl;
    }
    return 0;
}

(H)

在N*N的方格棋盤放置了N個皇后,使得它們不相互攻擊(即任意2個皇后不允許處在同一排,同一列,也不允許處在與棋盤邊框成45角的斜線上。
你的任務是,對於給定的N,求出有多少種合法的放置方法。

Input

共有若干行,每行一個正整數N≤10,表示棋盤和皇后的數量;如果N=0,表示結束。

Output

共有若干行,每行一個正整數,表示對應輸入行的皇后的不同放置數量。

Sample Input

1
8
5
0

Sample Output

1
92
10

題解:

#include "bits/stdc++.h"
using namespace std;
int book[110];
int a[11];
int ans = 0;
int n;
int t;
bool judge(int m,int z)
{
    for(int i = 1;i < m;i++){
        if(book[i] == z)   return false;//如果這一行已經有皇后了
        if(book[i] - i == z - m )  return false;//匹配兩條斜線上的棋子
        if(i + book[i] == m + z)  return false;//
    }
    return true;
}
void dfs(int cnt)
{
    if(t + 1 == cnt)//如果找到了一組解
    {
        ans++;
        return;
    }
    for(int i = 1;i <= t;i++){
        if(judge(cnt,i)){
            book[cnt] = i;
            dfs(cnt + 1);
            book[cnt] = 0;//回溯
        }    
    }
    return;
}
int main()
{
    a[1] = 1;
    for(t = 2;t <= 10;t++){//直接打表,不然超時
        dfs(1);
        a[t] = ans;
        ans = 0;
    }
    while(scanf("%d",&n) != EOF && n != 0)
        printf("%d\n",a[n]);
}