スタックとキューを用いたプログラミング課題解説

1. 多項式微分計算

係数と指数のペアを読み込み、微分計算を行い結果を出力する。

入力例:

3 4 -5 2 6 1 -2 0

出力例:

12 3 -10 1 6 0

実装例:

#include <iostream>
using namespace std;

int main() {
    int coeff, exp;
    bool first = true;
    
    while(cin >> coeff >> exp) {
        if(exp != 0) {
            if(!first) cout << " ";
            cout << coeff * exp << " " << exp - 1;
            first = false;
        }
    }
    
    if(first) {
        cout << "0 0";
    }
    
    return 0;
}

2. スタック操作の検証

一連のスタック操作が有効かどうかを判定する。操作は'S'(push)と'X'(pop)で表される。

入力例:

4 10
SSSXXSXXSX
SSSXXSXXS
SSSSSSSSSSXSSXXXXXXXXXXX
SSSXXSXXX

出力例:

YES
NO
NO
NO

実装例:

#include <stdio.h>
#include <string.h>

int main() {
    char operations[101];
    int testCount, maxSize;
    scanf("%d %d", &testCount, &maxSize);
    
    for(int i = 0; i < testCount; i++) {
        scanf("%s", operations);
        int stackSize = 0;
        int isValid = 1;
        
        for(int j = 0; operations[j] != '\0'; j++) {
            if(operations[j] == 'S') {
                stackSize++;
            } else {
                stackSize--;
            }
            
            if(stackSize < 0 || stackSize > maxSize) {
                isValid = 0;
                break;
            }
        }
        
        if(isValid && stackSize == 0) {
            printf("YES\n");
        } else {
            printf("NO\n");
        }
    }
    
    return 0;
}

3. 括弧とコメントの整合性チェック

プログラムコード中の括弧とコメント記号の対応を検証する。

実装例:

#include <stdio.h>
#include <stdlib.h>

#define MAX_SIZE 100

typedef struct {
    char data[MAX_SIZE];
    int top;
} CharStack;

void initStack(CharStack *s) {
    s->top = -1;
}

void push(CharStack *s, char ch) {
    if(s->top < MAX_SIZE - 1) {
        s->data[++(s->top)] = ch;
    }
}

char pop(CharStack *s) {
    if(s->top >= 0) {
        return s->data[(s->top)--];
    }
    return '\0';
}

char peek(CharStack *s) {
    if(s->top >= 0) {
        return s->data[s->top];
    }
    return '\0';
}

int isEmpty(CharStack *s) {
    return s->top == -1;
}

int main() {
    CharStack stack;
    initStack(&stack);
    char buffer[101];
    int valid = 1;
    char mismatch = '\0';
    
    while(scanf("%s", buffer) != EOF && buffer[0] != '.') {
        for(int i = 0; buffer[i] != '\0'; i++) {
            if(buffer[i] == '(' || buffer[i] == '[' || buffer[i] == '{') {
                push(&stack, buffer[i]);
            } else if(buffer[i] == '/' && buffer[i+1] == '*') {
                push(&stack, '/');
                push(&stack, '*');
                i++;
            } else if(buffer[i] == ')') {
                if(!isEmpty(&stack) && peek(&stack) == '(') {
                    pop(&stack);
                } else {
                    valid = 0;
                    mismatch = buffer[i];
                    break;
                }
            } else if(buffer[i] == ']') {
                if(!isEmpty(&stack) && peek(&stack) == '[') {
                    pop(&stack);
                } else {
                    valid = 0;
                    mismatch = buffer[i];
                    break;
                }
            } else if(buffer[i] == '}') {
                if(!isEmpty(&stack) && peek(&stack) == '{') {
                    pop(&stack);
                } else {
                    valid = 0;
                    mismatch = buffer[i];
                    break;
                }
            } else if(buffer[i] == '*' && buffer[i+1] == '/') {
                if(!isEmpty(&stack) && peek(&stack) == '*') {
                    pop(&stack);
                    if(!isEmpty(&stack) && peek(&stack) == '/') {
                        pop(&stack);
                    } else {
                        valid = 0;
                        mismatch = buffer[i];
                        break;
                    }
                } else {
                    valid = 0;
                    mismatch = buffer[i];
                    break;
                }
                i++;
            }
        }
        if(!valid) break;
    }
    
    if(valid && isEmpty(&stack)) {
        printf("YES\n");
    } else {
        printf("NO\n");
        if(!isEmpty(&stack)) {
            char top = peek(&stack);
            if(top == '(') printf("(-?\n");
            else if(top == '[') printf("[-?\n");
            else if(top == '{') printf("{-?\n");
            else if(top == '*') printf("/*-?\n");
        } else {
            if(mismatch == ')') printf("?-)\n");
            else if(mismatch == ']') printf("?-]\n");
            else if(mismatch == '}') printf("?-}\n");
            else if(mismatch == '*') printf("?-*/\n");
        }
    }
    
    return 0;
}

4. 数式中置記法から後置記法への変換

算術式を中置記法から後置記法に変換する。

実装例:

#include <stdio.h>
#include <ctype.h>

int precedence(char op) {
    if(op == '+' || op == '-') return 1;
    if(op == '*' || op == '/') return 2;
    return 0;
}

int main() {
    char expr[100];
    char stack[100];
    int top = -1;
    int spaceNeeded = 0;
    
    scanf("%s", expr);
    
    for(int i = 0; expr[i] != '\0'; i++) {
        if(isdigit(expr[i]) || expr[i] == '.') {
            if(spaceNeeded) printf(" ");
            printf("%c", expr[i]);
            spaceNeeded = 0;
        } else if(expr[i] == '(') {
            stack[++top] = expr[i];
        } else if(expr[i] == ')') {
            while(top >= 0 && stack[top] != '(') {
                printf(" %c", stack[top--]);
            }
            if(top >= 0) top--;
        } else {
            if(i == 0 && expr[i] == '-') {
                printf("-");
                continue;
            }
            
            if((expr[i] == '+' || expr[i] == '-') && 
               (i == 0 || expr[i-1] == '(' || 
                expr[i-1] == '+' || expr[i-1] == '-' || 
                expr[i-1] == '*' || expr[i-1] == '/')) {
                if(spaceNeeded) printf(" ");
                printf("%c", expr[i]);
                spaceNeeded = 0;
                continue;
            }
            
            while(top >= 0 && precedence(stack[top]) >= precedence(expr[i])) {
                printf(" %c", stack[top--]);
            }
            stack[++top] = expr[i];
            spaceNeeded = 1;
        }
    }
    
    while(top >= 0) {
        printf(" %c", stack[top--]);
    }
    
    return 0;
}

5. 銀行窓口振り分けシミュレーション

顧客を奇数番号と偶数番号の二つの窓口に振り分け、処理順序を決定する。

実装例:

#include <stdio.h>

int main() {
    int customers[1000];
    int oddQueue[1000], evenQueue[1000];
    int oddCount = 0, evenCount = 0;
    int n;
    
    scanf("%d", &n);
    
    for(int i = 0; i < n; i++) {
        scanf("%d", &customers[i]);
        if(customers[i] % 2 == 1) {
            oddQueue[oddCount++] = customers[i];
        } else {
            evenQueue[evenCount++] = customers[i];
        }
    }
    
    int oddIdx = 0, evenIdx = 0;
    int firstPrinted = 0;
    
    while(oddIdx < oddCount || evenIdx < evenCount) {
        if(oddIdx < oddCount) {
            if(firstPrinted) printf(" ");
            printf("%d", oddQueue[oddIdx++]);
            firstPrinted = 1;
        }
        if(oddIdx < oddCount) {
            printf(" %d", oddQueue[oddIdx++]);
        }
        if(evenIdx < evenCount) {
            printf(" %d", evenQueue[evenIdx++]);
        }
    }
    
    return 0;
}

タグ: スタック キュー データ構造 アルゴリズム C言語

5月21日 07:32 投稿