Post

덱(Deque, Double-Ended Queue) — 자료구조와 활용

덱(Deque, Double-Ended Queue) — 자료구조와 활용

1. 덱 개념

덱은 양쪽 끝에서 삽입과 삭제가 모두 가능한 자료구조입니다. 큐(Queue)와 스택(Stack)의 특성을 모두 가지며, 데이터를 앞이나 뒤에서 넣고 뺄 수 있습니다.

2. 기본 연산

  • append(item): 덱의 뒤쪽에 데이터(item)를 추가합니다. (뒤쪽 삽입)
  • prepend(item): 덱의 앞쪽에 데이터(item)를 추가합니다. (앞쪽 삽입)
  • popFront(): 덱의 앞쪽 데이터를 제거하고 반환합니다.
  • popBack(): 덱의 뒤쪽 데이터를 제거하고 반환합니다.
  • peekFront(): 앞쪽 데이터를 제거하지 않고 반환합니다.
  • peekBack(): 뒤쪽 데이터를 제거하지 않고 반환합니다.
  • isEmpty(): 덱이 비어 있는지 확인합니다.

3. 내부 구조

덱은 배열, 연결 리스트, 원형 버퍼 등으로 구현합니다.

  • 배열 기반은 뒤쪽 삽입/삭제는 빠르지만, 앞쪽 작업은 비용이 발생할 수 있어 효율적 구현을 위해 원형 배열을 사용하기도 합니다.
  • 연결 리스트 기반은 앞뒤 노드를 바로 접근할 수 있어 양쪽 연산 모두 효율적입니다.

4. 활용 사례

  • 양방향 탐색: BFS나 최단 경로 알고리즘에서 앞뒤로 노드를 추가/삭제해야 할 때.
  • 슬라이딩 윈도우 문제: 배열이나 리스트에서 일정 범위 내 최대/최소값을 빠르게 찾을 때.
  • 텍스트 편집기: 커서 이동 시 앞뒤 문자를 빠르게 삽입/삭제할 때.

5. 코드 예시 (Swift)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
struct Deque<T> {
    private var elements = [T]()
    
    mutating func append(_ item: T) {
        elements.append(item)
    }
    
    mutating func prepend(_ item: T) {
        elements.insert(item, at: 0)
    }
    
    mutating func popFront() -> T? {
        guard !elements.isEmpty else { return nil }
        return elements.removeFirst()
    }
    
    mutating func popBack() -> T? {
        return elements.popLast()
    }
    
    func peekFront() -> T? {
        return elements.first
    }
    
    func peekBack() -> T? {
        return elements.last
    }
    
    var isEmpty: Bool {
        return elements.isEmpty
    }
}

6. 마무리

덱은 양쪽 끝에서 유연하게 데이터를 넣고 뺄 수 있어 다양한 알고리즘과 시스템에서 활용됩니다. 큐와 스택의 장점을 합친 자료구조로, 문제에 따라 적절히 선택해 사용하면 효율적인 구현이 가능합니다.

This post is licensed under CC BY 4.0 by the author.