1. 스택(Stack)
개념
- LIFO(Last In First Out, 후입선출) 구조
- 가장 나중에 들어온 데이터가 가장 먼저 나가는 형태
- 입구가 출구가 하나인 구조
주요 연산
- push : 데이터를 넣는 연산 (top 위치에 삽입)
- pop : 데이터를 꺼내는 연산 (top 위치 데이터 삭제 및 반환)
- peek : 데이터를 꺼내지 않고 확인만 하는 연산
활용
- DFS(깊이 우선 탐색)
- 백트래킹 (Backtracking)
- 재귀 함수의 원리와 동일
Java 구현
Java에서 스택을 사용할 때 java.util.Stack 클래스는 사용을 지양해야 한다.
- 이유 : Stack은 초기 Java 버전의 Vector를 상속받아 구현되어 있어, 모든 메서드에 동기화(Synchronized) 키워드가 붙어 있다. 이는 멀티 스레드 환경이 아닐 때 불필요한 오버헤드를 발생시킨다.
- 대안 : Deque 인터페이스의 구현체인 ArrayDeque를 사용하는 것이 성능면에서 유리하다.
예시)
// 비추천 (Legacy)
Stack<Integer> stack = new Stack<>();
// 추천 (Modern Java)
Deque<Integer> stack = new ArrayDeque<>();
stack.push(1);
stack.push(2);
stack.peek(); // 2 출력
stack.pop(); // 2 반환 및 삭제
2. 큐(Queue)
개념
- FIFO (First In First Out, 선입선출) 구조
- 먼저 들어온 데이터가 먼저 나가는 형태
- 양쪽이 뚫려있는 구조
주요 연산
- add / offer : 데이터를 넣는 연산 (rear/tail 위치에 삽입). offer는 실패 시 예외 대신 false를 반환하므로 더 안정적
- remove / poll : 데이터를 꺼내는 연산 (front/head 위치 데이터 삭제 및 변환) poll은 비어 있을 때 null을 반환
- element / peek : 데이터를 확인만 하는 연산
활용
- BFS (너비 우선 탐색)
- 캐시(Cache) 구현
- 프로세스 스케줄링
Java 구현(LinkedList vs ArrayDeque)
Queue는 인터페이스이므로 구현체가 필요하다. 보통 LinkedList와 ArrayDeque 중 하나를 선택한다.
- LinkedList : 큐의 중간에 데이터를 삽입/삭제할 일이 많다면 유리하다. 하지만 각 요소가 노드 객체로 생성되므로 메모리 오버헤드가 있다.
- ArrayDeque : 큐의 양 끝에서만 연산이 일어난다면(순수 큐 기능) 메모리 효율과 속도(Cache Locality)면에서 LinkedList 보다 유리하다.
예시)
// 일반적인 구현 (LinkedList 사용)
Queue<Integer> queue = new LinkedList<>();
// 성능 중시 (ArrayDeque 사용)
Queue<Integer> queue = new ArrayDeque<>();
queue.offer(1);
queue.offer(2);
queue.peek(); // 1 출력 (먼저 들어간 값)
queue.poll(); // 1 반환 및 삭제
3. 우선순위 큐(Priority Queue)
- 들어간 순서와 상관 없이 우선순위가 높은 데이터가 먼저 나오는 자료구조
- 힙(Heap) 자료구조를 기반으로 구현
- Java에서는 PriorityQueue 클래스를 사용하며, 기본적으로 낮은 숫자(Min Heap)가 높은 우선순위를 가진다.(높은 숫자를 우선시 하려면 Collections.reverseOrder() 사용)
예시)
// 낮은 숫자가 우선 (Min Heap)
PriorityQueue<Integer> pq = new PriorityQueue<>();
// 높은 숫자가 우선 (Max Heap)
PriorityQueue<Integer> pq = new PriorityQueue<>(Collections.reverseOrder());
정리
스택과 큐는 알고리즘 문제 해결의 도구다. 단순히 메서드만 아는 것보다, 문제의 성격(DFS 또는 BFS)에 따라 적절한 자료구조를 선택하고, 효율적인 구현체(ArrayDeque)를 선택하는 것이 중요하다.
'Programming > Algorithm' 카테고리의 다른 글
| [Algorithm] 구간 합 (Prefix Sum) 핵심 개념 및 활용 (0) | 2026.02.03 |
|---|---|
| [Algorithm] 배열(Array) vs 리스트(List) 비교 및 선택 기준 (1) | 2026.01.30 |
| [Algorithm] 코딩테스트 디버깅(Debugging) 핵심 요령 및 실수 유형 (0) | 2026.01.23 |
| [Algorithm] 시간 복잡도 (Time Complexity) 개념 및 Big-O 표기법 (0) | 2026.01.22 |
