python
python - 스택(Stack) 자료구조
해보쟈
2025. 1. 25. 17:13
1. 스택의 개념
- 스택(Stack): 선형 자료구조, LIFO(Last In, First Out) 방식으로 작동.
- 가장 나중에 삽입된 데이터가 가장 먼저 제거됨. (예: 접시 쌓기)
2. 스택의 특징
- LIFO 구조 : 마지막 들어간 데이터가 가장 먼저 나옴.
- 주요 연산 :
- push: 데이터를 스택의 맨 위에 추가.
- pop: 스택의 맨 위 데이터를 제거하고 반환.
- peek (또는 top): 스택의 맨 위 데이터를 제거하지 않고 확인.
- is_empty: 스택이 비어 있는지 확인.
- 실제 구현 :
- 리스트를 사용하여 스택을 구현하거나, collections.deque를 사용하여 더 효율적인 스택을 구현할 수 있다.
3. 스택의 구현 방법
(1) 리스트를 이용한 스택
- Python의 리스트는 기본적으로 스택처럼 사용할 수 있음.
# 스택 구현
stack = []
# push: 데이터 추가
stack.append(1)
stack.append(2)
stack.append(3)
print("스택 상태:", stack) # [1, 2, 3]
# pop: 데이터 제거
top = stack.pop()
print("제거된 데이터:", top) # 3
print("스택 상태:", stack) # [1, 2]
# peek: 맨 위 데이터 확인
top = stack[-1]
print("맨 위 데이터:", top) # 2
# is_empty: 스택이 비어 있는지 확인
is_empty = len(stack) == 0
print("스택이 비어 있나요?", is_empty) # False
(2) collecttions.deque를 이용한 스택
- 리스트는 동적 배열 기반이므로, 크기가 커질수록 append와 pop의 성능이 느려질 수 있다.
- deque는 양방향 큐로 구현되어 있어 더 빠르게 동작한다.
from collections import deque
# 스택 구현
stack = deque()
# push: 데이터 추가
stack.append(1)
stack.append(2)
stack.append(3)
print("스택 상태:", stack) # deque([1, 2, 3])
# pop: 데이터 제거
top = stack.pop()
print("제거된 데이터:", top) # 3
print("스택 상태:", stack) # deque([1, 2])
# peek: 맨 위 데이터 확인
top = stack[-1]
print("맨 위 데이터:", top) # 2
# is_empty: 스택이 비어 있는지 확인
is_empty = len(stack) == 0
print("스택이 비어 있나요?", is_empty) # False
4. 스택의 활용
(1) 괄호 짝 검사
- 문자열의 괄호가 올바른지 확인.
- 스택을 사용하여 여는 괄호를 저장하고, 닫는 괄호가 나왔을 때 매칭되는 여는 괄호를 제거
def is_valid_parentheses(s):
stack = []
mapping = {')': '(', '}': '{', ']': '['}
for char in s:
if char in mapping.values(): # 여는 괄호
stack.append(char)
elif char in mapping.keys(): # 닫는 괄호
if not stack or stack[-1] != mapping[char]:
return False
stack.pop() # 매칭되는 여는 괄호 제거
return not stack
# 테스트
print(is_valid_parentheses("(){}[]")) # True
print(is_valid_parentheses("([{}])")) # True
print(is_valid_parentheses("(]")) # False
(2) 문자열 뒤집기
def reverse_string(s):
stack = []
for char in s:
stack.append(char)
reversed_str = ""
while stack:
reversed_str += stack.pop()
return reversed_str
# 테스트
print(reverse_string("hello")) # "olleh"
(3) DFS(깊이 우선 탐색)
- 스택은 그래프 탐색에서 DFS 구현할 때 사용된다.
def dfs(graph, start):
visited = set()
stack = [start]
while stack:
node = stack.pop()
if node not in visited:
visited.add(node)
print(node, end=" ") # 방문 순서 출력
stack.extend(graph[node]) # 이웃 노드 추가
# 그래프 인접 리스트
graph = {
1: [2, 3],
2: [4, 5],
3: [],
4: [],
5: []
}
dfs(graph, 1) # 출력: 1 3 2 5 4
5. 스택의 장단점
장점
- 간단한 구현: Python 리스트나 deque로 간단히 구현 가능.
- 다양한 활용: 괄호 검사, 문자열 처리, DFS 등 다양한 문제 해결 가능.
- 빠른 데이터 접근: 맨 위 데이터(peek) 접근이 O(1).
단점
- 순차적 접근: 특정 데이터에 접근하려면 스택을 모두 순회해야 함.
- 제한된 구조: LIFO 방식으로 인해 일부 문제에는 적합하지 않음.
6. 실습 문제
문제 1: 히스토그램에서 가장 큰 직사각형
- 문제 : 히스토그램의 막대 높이가 주어질 때, 가장 큰 직사각형의 면적을 구하시오.
- 풀이 : 스택을 사용하여 효율적으로 최대 면적 계산.
def largest_rectangle_area(heights):
stack = []
max_area = 0
heights.append(0) # 끝부분에 0을 추가해 모든 높이를 처리
for i, h in enumerate(heights):
while stack and heights[stack[-1]] > h:
height = heights[stack.pop()]
width = i if not stack else i - stack[-1] - 1
max_area = max(max_area, height * width)
stack.append(i)
return max_area
# 테스트
print(largest_rectangle_area([2, 1, 5, 6, 2, 3])) # 출력: 10