스택, 큐와 덱
LIFO·FIFO 구조와 원형 큐, 덱의 연산 과정을 문제 풀이 중심으로 학습한다.
1. 스택
스택은 한쪽 끝인 top에서만 삽입과 삭제가 일어나는 LIFO(Last In, First Out) 구조이다.
- 삽입:
push - 삭제:
pop - 최상단 확인:
peek또는top - 비어 있는 스택에서 삭제하면 underflow, 저장 공간을 넘어서 삽입하면 overflow가 발생한다.
대표 활용
- 함수 호출과 복귀 주소 관리
- 재귀 호출
- 괄호 검사
- 중위식을 후위식으로 변환하거나 후위식을 계산
- 실행 취소, 브라우저 뒤로 가기
- 깊이 우선 탐색(DFS)
후위식 6 2 3 + *은 스택으로 계산한다. 2+3=5를 먼저 계산하고 6×5=30이 된다.
2. 큐
큐는 rear에서 삽입하고 front에서 삭제하는 FIFO(First In, First Out) 구조이다.
- 삽입:
enqueue - 삭제:
dequeue - 대표 활용: CPU 준비 큐, 프린터 작업, 네트워크 버퍼, 너비 우선 탐색(BFS)
선형 배열 큐는 앞쪽 공간이 비어도 rear가 배열 끝에 도달하면 공간을 활용하지 못하는 가짜 포화(false overflow) 문제가 생길 수 있다. 이를 해결하는 구조가 원형 큐이다.
원형 큐
크기가 N인 배열에서 인덱스는 (index + 1) mod N으로 순환한다. 구현 방식에 따라 한 칸을 비워 두면 다음 조건을 사용한다.
공백: front == rear
포화: (rear + 1) mod N == front
구현마다 front가 첫 원소를 가리키는지, 첫 원소 직전 위치를 가리키는지가 다르므로 문제에서 정의를 확인해야 한다.
3. 덱과 우선순위 큐
- 덱(deque): 양쪽 끝에서 삽입과 삭제가 모두 가능하다.
- 입력 제한 덱: 한쪽에서만 삽입한다.
- 출력 제한 덱: 한쪽에서만 삭제한다.
- 우선순위 큐: 먼저 들어온 순서가 아니라 우선순위가 높은 원소를 먼저 제거한다. 보통 힙으로 구현한다.
4. 연산 비교
| 구조 | 원칙 | 삽입 위치 | 삭제 위치 | 대표 활용 |
|---|---|---|---|---|
| 스택 | LIFO | top | top | 함수 호출, DFS |
| 큐 | FIFO | rear | front | 스케줄링, BFS |
| 덱 | 양방향 | 양쪽 | 양쪽 | 슬라이딩 윈도, 양방향 처리 |
| 우선순위 큐 | 우선순위 | 구조에 따라 | 최고·최저 우선순위 | 작업 선택, 최단경로 |
5. 배열 구현과 상태 표현
스택은 보통 top이 마지막 원소 인덱스를 가리키도록 구현한다. 빈 스택을 top=-1로 두면 push 후 증가 또는 증가 후 저장 중 어떤 규칙인지 일관되어야 한다.
stack = []
stack.append(10) # push
x = stack.pop() # pop
원형 큐는 구현 정의를 먼저 확인한다.
한 칸 비우기 방식
공백: front == rear
포화: (rear + 1) % N == front
저장 가능 원소 수: N - 1
현재 원소 수: (rear - front + N) % N
front가 첫 원소 직전을 가리키는 구현에서는 삭제할 때 먼저 front=(front+1)%N을 수행한 뒤 원소를 읽는다.
6. 원형 큐 상태 추적 예제
크기 6, 한 칸 비우기 방식에서 처음 front=rear=0이라고 하자. 11, 22, 33을 삽입하면 rear=3이고, 두 번 삭제하면 front=2이다. 이어 44, 55, 66을 삽입하면 rear는 0으로 순환한다.
index : 0 1 2 3 4 5
value : 66 - - 33 44 55
front=2, rear=0
논리적 순서: 33 → 44 → 55 → 66
배열의 물리적 인덱스 순서와 큐의 논리적 순서를 혼동하지 않는다.
7. 중위식·후위식과 스택
후위식 계산은 값을 스택에 넣고 연산자를 만나면 오른쪽 피연산자, 왼쪽 피연산자 순으로 꺼낸다.
b = stack.pop() # 오른쪽
a = stack.pop() # 왼쪽
stack.append(a - b)
중위식을 후위식으로 바꿀 때는 연산자 우선순위와 괄호를 스택으로 관리한다. 예를 들어 A*(B+C)-D는 ABC+*D-가 된다.
8. 덱의 응용
덱은 단순히 양쪽 큐가 아니다. 다음 문제에서 핵심 도구가 된다.
- 슬라이딩 윈도 최댓값: 값이 감소하는 순서를 유지하는 단조 덱
- 0-1 BFS: 가중치 0 간선은 앞, 가중치 1 간선은 뒤에 삽입
- 최근 항목 유지, 양방향 작업 스케줄링
단조 스택은 다음 큰 원소, 히스토그램 최대 직사각형처럼 “아직 답을 찾지 못한 후보”를 순서 있게 유지한다.
9. 우선순위 큐와 큐의 구분
우선순위 큐는 삽입 순서가 아니라 우선순위에 따라 삭제한다. 힙 구현에서는 삽입·삭제가 O(log n), 최우선 원소 확인이 O(1)이다. 같은 우선순위 사이의 FIFO는 별도 순번을 함께 저장하지 않으면 보장되지 않을 수 있다.
10. 선택 기준
| 상황 | 적합한 구조 |
|---|---|
| 최근 호출부터 복귀 | 스택 |
| 도착 순서대로 처리 | 큐 |
| 양끝 삽입·삭제 | 덱 |
| 중요도가 높은 작업부터 처리 | 우선순위 큐 |
| 일정 크기 구간의 최댓값 반복 | 단조 덱 |
최종 확인 문제
- 크기 8인 한 칸 비우기 원형 큐에서
front=6,rear=2일 때 저장된 원소 수를 구하시오. - 후위식
8 3 1 - / 2 *의 값을 구하시오. A+(B*C-D)/E를 후위식으로 나타내시오.- 동일 우선순위 작업의 도착 순서를 반드시 보존하려면 우선순위 큐 원소에 무엇을 함께 저장할 수 있는가?
- 슬라이딩 윈도 최댓값을 O(n)에 구할 때 사용하는 대표 구조와 유지 조건을 설명하시오.