C++
 Computer >> コンピューター >  >> プログラミング >> C++

C++で括弧のバランスを判定する方法:スタックを使った有効な括弧チェック

問題の概要

ある式が与えられたとき、その式に含まれる括弧が正しく対応している(バランスしている)かどうかを判定します。対象となる括弧は (){}[] の3種類です。

例えば、「()[(){()}]」は開き括弧と閉じ括弧が正しい順序で対応しているため有効な式です。一方、「{[}]」は括弧の入れ子関係が崩れているため無効となります。

アルゴリズムの考え方:スタックを活用する

この問題はスタック(stack)というデータ構造を使うことで、シンプルかつ効率的に解決できます。手順は以下の通りです。

  • 式を先頭から最後まで走査する
    • 現在の文字が開き括弧(({[)の場合 → スタックにプッシュする
    • 現在の文字が閉じ括弧()}])の場合 → スタックからポップし、取り出した開き括弧が現在の閉じ括弧と対応しているかを確認する。対応していれば問題なし、そうでなければその式はバランスしていない
  • 走査終了後の確認 → 文字列をすべて処理した後もスタックに開き括弧が残っている場合は、閉じられていない括弧が存在するため、その式はバランスしていないと判定する

この手法により、計算量は式の長さを n としたとき O(n) で済みます。

C++での実装例

#include <iostream>
#include <stack>
using namespace std;
bool isBalancedExp(string exp) {
    stack<char> stk;
    char x;
    for (int i=0; i<exp.length(); i++) {
        if (exp[i]=='('||exp[i]=='['||exp[i]=='{') {
            stk.push(exp[i]);
            continue;
        }
        if (stk.empty())
            return false;
        switch (exp[i]) {
        case ')':
            x = stk.top();
            stk.pop();
            if (x=='{' || x=='[')
                return false;
            break;
        case '}':
            x = stk.top();
            stk.pop();
            if (x=='(' || x=='[')
                return false;
            break;
        case ']':
            x = stk.top();
            stk.pop();
            if (x =='(' || x == '{')
                return false;
            break;
        }
    }
    return (stk.empty());
}
int main() {
    string expresion = "()[(){()}]";
    if (isBalancedExp(expresion))
        cout << "This is Balanced Expression";
    else
        cout << "This is Not Balanced Expression";
}

実行結果

入力

"()[(){()}]"

出力

This is Balanced Expression

まとめ

括弧の対応チェックは、スタックの「後入れ先出し(LIFO)」の性質を利用することで自然に実装できます。開き括弧をプッシュし、閉じ括弧が出たら直近の開き括弧と照合する——この流れさえ押さえれば、ネストされた複雑な式でも確実に判定可能です。コンパイラや構文解析ツールなどでも使われる基本的なテクニックなので、ぜひマスターしておきましょう。

  1. C++で文字列から無効な括弧を削除し、有効な括弧列をすべて出力する方法

    括弧を含む文字列が与えられたとき、無効な括弧を取り除くことで得られる、考えられるすべての有効な括弧列を出力する問題を考えてみましょう。まずは具体例から見ていきます。 入力 : str = ()())() 出力 : ()()() (())() 2つの解が存在します ()()() と (())() 入力 : str = (v)())() 出力 : (v)()() (v())() この問題では、バックトラッキングの考え方を用いることで、条件を満たすすべての有効な文字列を出力できます。 解決のためのアプローチ このアプローチでは、BFS(幅優先探索)を使って、開き括弧と閉じ括弧を1つずつ順番に削除

  2. C++で数独の有効性を判定するアルゴリズムを解説

    9×9の行列で表される数独(Sudoku)が与えられたとします。この課題の目的は、与えられた数独の配置が有効かどうかを判定することです。一般的な数独の盤面は次のようになります。数独のルール各行には1〜9の範囲の数字が入る各列には1〜9の範囲の数字が入る各3×3のブロックには重複のない数字が入る同じ行に同じ数字が現れることはできない同じ列に同じ数字が現れることはできない入出力の例入力例:sudoku[]= [[3,5,.,.,2,.,.,.,.] ,[7,.,.,1,6,5,.,.,.] ,[.,9,8,.,.,.,.,6,.] ,[8,.,.,.,6,.,.,.