Brackets validation with a stack
A string of brackets is balanced when every opening symbol ( [ { has a matching closing symbol in the right order—like nested function calls unwinding. A stack fits naturally: push each opener; on a closer, the most recent opener on the stack must pair with it. If the stack is empty when you need a match, or types do not match (( with ]), the string is invalid. After scanning, the stack must be empty. Time is O(n) for length n.
- Rules — push openers, match closers
- Pairs —
()[]{} - Example in C — char stack,
scanf - Traces — valid
([{}])vs invalid([)]
1) Matching rules
Scan the string once, left to right. Characters that are not brackets are ignored in the program below (so {a+b} is checked only on { and }).
| Character | Action |
|---|---|
( [ { |
Push onto the stack. |
) ] } |
If stack is empty → invalid. Otherwise pop the top opener; it must pair with this closer (same type). If not → invalid. |
| Anything else | Ignore (skip) for bracket-only validation. |
| End of string | If stack is empty → valid; else invalid (unclosed openers). |
2) Pairing table
| Open | Close |
|---|---|
( |
) |
[ |
] |
{ |
} |
3) Example in C
A fixed-size char array acts as the stack; top == -1 means empty. The program reads one token with scanf("%s", ...) (no spaces inside the string).
#include <stdio.h>
#define MAX 100
char stack[MAX];
int top = -1;
// Push opening bracket
void push(char c) {
stack[++top] = c;
}
// Pop opening bracket
char pop(void) {
return stack[top--];
}
// Stack empty?
int is_empty(void) {
return top < 0;
}
// Does this open/close pair match?
int matches(char open, char close) {
if (open == '(')
return close == ')';
if (open == '[')
return close == ']';
if (open == '{')
return close == '}';
return 0;
}
// 1 = valid, 0 = invalid
int is_valid(const char *s) {
int i;
top = -1;
for (i = 0; s[i] != '\0'; i++) {
char c = s[i];
if (c == '(' || c == '[' || c == '{')
push(c);
else if (c == ')' || c == ']' || c == '}') {
if (is_empty())
return 0;
if (!matches(pop(), c))
return 0;
}
}
return is_empty();
}
int main(void) {
char s[MAX];
printf("Enter string: ");
scanf("%s", s);
if (is_valid(s))
printf("Valid brackets\n");
else
printf("Invalid brackets\n");
return 0;
}
Prefer scanf("%99s", s) with MAX == 100 or fgets to cap length. Check top < MAX - 1 before push to avoid overflow. To reject non-bracket characters instead of skipping them, add an else branch that returns 0.
Trace — valid ([{}])
Stack entries are listed bottom → top.
| Step | Char | Action | Stack |
|---|---|---|---|
| 1 | ( |
Push | ( |
| 2 | [ |
Push | ( [ |
| 3 | { |
Push | ( [ { |
| 4 | } |
Pop {, matches |
( [ |
| 5 | ] |
Pop [, matches |
( |
| 6 | ) |
Pop (, matches |
(empty) |
| 7 | end | Stack empty → valid | — |
Trace — invalid ([)]
| Step | Char | Action | Stack |
|---|---|---|---|
| 1 | ( |
Push | ( |
| 2 | [ |
Push | ( [ |
| 3 | ) |
Pop [; [ does not pair with ) → invalid |
— |
| Input | Output | Reason |
|---|---|---|
([{}]) |
Valid brackets |
All pairs close in LIFO order. |
([)] |
Invalid brackets |
) meets [ on top—wrong type. |
(( |
Invalid brackets |
End of string with unclosed (. |
{a+b} |
Valid brackets |
Letters skipped; { and } match. |
Key points
| Idea | Explanation |
|---|---|
| LIFO | The last opener must match the next closer—exactly stack pop order. |
| Empty stack on closer | ) with no matching ( on the stack is invalid (e.g. )((). |
| Related topics | Expression parsing also uses stacks—see Infix to postfix and Stack applications. |
4) Trade-offs
- Pros — One pass, simple array stack, classic interview pattern.
- Cons — Fixed
MAX; for Unicode or multi-char “brackets” you need a richer model.
Introductory stack ideas: Stack introduction · Stack using array.
Key takeaway
Treat opening brackets as work to finish later: push them. Each closing bracket must complete the most recent unfinished opener—pop and check the pair. Valid means every opener was closed and nothing is left on the stack.
See also: Stack applications · Infix to postfix · Stack tutorial