• Feed
  • Explore
  • Ranking
/
/
    CS

    Deque

    덱(deque, double-ended queue)은 양쪽 끝에서 데이터의 삽입과 삭제가 모두 가능한 자료구조로, 큐와 스택을 합친 형태이다.
    Deque
    e
    efforthye
    in
    CS
    2025.06.15
    ·
    5 min read

    덱(deque, double-ended queue)은 양쪽 끝에서 데이터의 삽입과 삭제가 모두 가능한 자료구조로, 큐와 스택을 합친 형태이다.

    6815

    코드 예시

    // 간단한 함수형 Deque
    type Deque<T> = T[]; // 덱을 배열 타입으로 정의, T는 제네릭 타입 매개변수
    
    // 덱의 앞쪽에 요소를 추가하는 함수
    const addFront = <T>(deque: Deque<T>, item: T): Deque<T> => 
      [item, ...deque]; // 새 요소를 맨 앞에, 기존 배열을 스프레드로 뒤에 붙임
    
    // 덱의 뒤쪽에 요소를 추가하는 함수  
    const addRear = <T>(deque: Deque<T>, item: T): Deque<T> => 
      [...deque, item]; // 기존 배열을 스프레드로 앞에, 새 요소를 맨 뒤에 붙임
    
    // 덱의 앞쪽 요소를 제거하는 함수
    const removeFront = <T>(deque: Deque<T>): [T | undefined, Deque<T>] => 
      [deque[0], deque.slice(1)]; // [제거된 첫 번째 요소, 첫 번째 제외한 나머지 배열]
    
    // 덱의 뒤쪽 요소를 제거하는 함수
    const removeRear = <T>(deque: Deque<T>): [T | undefined, Deque<T>] => 
      [deque[deque.length - 1], deque.slice(0, -1)]; // [마지막 요소, 마지막 제외한 배열]
    
    // 덱의 앞쪽 요소를 확인만 하는 함수 (제거하지 않음)
    const peekFront = <T>(deque: Deque<T>): T | undefined => 
      deque[0]; // 첫 번째 요소 반환, 빈 배열이면 undefined
    
    // 덱의 뒤쪽 요소를 확인만 하는 함수 (제거하지 않음)
    const peekRear = <T>(deque: Deque<T>): T | undefined => 
      deque[deque.length - 1]; // 마지막 요소 반환, 빈 배열이면 undefined
    
    // 사용 예시
    let deque: Deque<number> = []; // 숫자 타입의 빈 덱 생성
    
    deque = addRear(deque, 1);     // 뒤쪽에 1 추가 → [1]
    deque = addFront(deque, 0);    // 앞쪽에 0 추가 → [0, 1]  
    deque = addRear(deque, 2);     // 뒤쪽에 2 추가 → [0, 1, 2]
    
    console.log(deque);            // 전체 덱 출력: [0, 1, 2]
    console.log(peekFront(deque)); // 앞쪽 요소 확인: 0
    console.log(peekRear(deque));  // 뒤쪽 요소 확인: 2
    
    const [front, newDeque] = removeFront(deque); // 앞쪽 요소 제거, 구조분해할당으로 받기
    console.log(front);            // 제거된 요소: 0
    console.log(newDeque);         // 남은 덱: [1, 2]

    덱의 특징

    장점

    • 유연성: 스택 + 큐 기능을 모두 제공

    • 양방향 접근: 앞뒤 어디서든 O(1) 시간에 접근 (연결리스트 기반)

    • 다양한 활용: 슬라이딩 윈도우, 팰린드롬 검사 등

    단점 (배열 기반)

    • addFront, removeFront가 O(n) 시간 복잡도 (요소들을 이동해야 함)

    활용 사례

    팰린드롬 검사

    function isPalindrome(str: string): boolean {
      let deque = str.split('');
      
      while (deque.length > 1) {
        const [front] = removeFront(deque);
        const [rear, newDeque] = removeRear(deque);
        deque = newDeque;
        
        if (front !== rear) return false;
      }
      return true;
    }
    
    console.log(isPalindrome("racecar")); // true
    console.log(isPalindrome("hello"));   // false

    슬라이딩 윈도우

    // 최근 3개 요소의 합을 계속 계산
    let window: Deque<number> = [];
    
    function addToWindow(num: number): number {
      window = addRear(window, num);
      if (window.length > 3) {
        [, window] = removeFront(window);
      }
      return window.reduce((a, b) => a + b, 0);
    }
    
    // 사용 예시
    console.log(addToWindow(1)); // 1 (window: [1])
    console.log(addToWindow(2)); // 3 (window: [1, 2])
    console.log(addToWindow(3)); // 6 (window: [1, 2, 3])
    console.log(addToWindow(4)); // 9 (window: [2, 3, 4])

    브라우저 히스토리

    class BrowserHistory {
      private history: Deque<string> = [];
      private currentIndex = -1;
    
      visit(url: string): void {
        // 현재 위치 이후의 히스토리 제거
        this.history = this.history.slice(0, this.currentIndex + 1);
        this.history = addRear(this.history, url);
        this.currentIndex++;
      }
    
      back(): string | undefined {
        if (this.currentIndex > 0) {
          this.currentIndex--;
          return this.history[this.currentIndex];
        }
        return undefined;
      }
    
      forward(): string | undefined {
        if (this.currentIndex < this.history.length - 1) {
          this.currentIndex++;
          return this.history[this.currentIndex];
        }
        return undefined;
      }
    }

    결론

    위와 같이 Deque은 양쪽 끝에서 자유롭게 삽입/삭제가 가능한 가장 유연한 자료구조로, 스택과 큐의 모든 기능을 포함한다.







    - 컬렉션 아티클