티스토리 뷰

코딩테스트

[자료구조/JS] 📥 Queue

viscachas 2025. 9. 10. 13:55

Queue

  • 큐는 First In First Out입니다.
    👉 먼저 들어온 데이터가 가장 먼저 나가는 구조죠. (반면 스택은 Last In First Out)

즉, 순서대로 무언가를 처리할 때 쓰이는 자료구조입니다.

🎯 큐를 활용하는 분야

  • 작업 대기열: 네트워크 통신할 때 다수의 클라이언트가 서버에 작업을 요청하면 서버는 들어온 순서대로 작업을 처리해요.
  • 이벤트 처리: 어떤 애플리케이션이나 시스템에서 사용자의 이벤트. (ex: 키보드 입력이나 마우스의 움직임)

📐 큐의 ADT (Abstract Data Type)

🔧 연산

연산 설명 시간 복잡도
isFull() 큐가 꽉찼는지 확인 O(1)
isEmpty() 큐가 비어있는지 확인 O(1)
enqueue(item) isFull() false면, 아이템 푸시 O(1)
dequeue() isEmpty()가 false면, 제일 앞에 있는 값 팝하고 반환 O(1)

📊 상태

상태 설명
front 가장 최근에 꺼낸 위치
rear 가장 최근에 삽입한 위치
data[maxsize] 큐의 데이터를 관리하는 배열 (크기: maxsize)

⚡ JS로 큐 만들기

  • JS는 기본적으로 큐를 제공하지 않아요.
    👉 shift()를 흉내낼 수 있지만 O(n)이라 실제 큐의 성능을 기대할 수 없어요.
    그래서 배열이나 연결 리스트로 직접 구현하는 게 좋아요.

1️⃣ shift()로 흉내내기

  • shift()는 배열의 첫번째 요소를 제거 후, 나머지 요소들을 앞으로 당겨야 하기 때문에 비효율적이에요. => O(n)

2️⃣ 배열로 직접 구현하기

  • 배열은 단순하지만 front가 앞으로 이동하면서 dequeue한 공간이 낭비되는 단점이 있어요.
class Queue {
  constructor() {
    this.front = 0;
    this.rear = 0;
    this.maxSize = 1001; // maxsize를 임의로 1001로 두었다.
    this.data = Array(this.maxSize).fill(null);
  }

  enqueue(item) {
    if (isFull()) {
    }
    this.data.push(item);
    this.rear++;
  }

  dequeue() {
    if (isEmpty()) {
      return null;
    }
    return this.data[this.front++];
  }

  isFull() {
    return this.rear === this.maxSize - 1;
  }

  isEmpty() {
    return this.front === this.rear;
  }
}

3️⃣ 연결 리스트로 직접 구현하기

  • 연결 리스트는 동적 크기 조정이 가능하고, 사용하지 않는 메모리는 해제할 수 있어서 메모리 사용 측면에서 더 효율적이다.
class Node {
  constructor(item) {
    this.data = item;
    this.next = null;
  }
}

class Queue {
  constructor() {
    this.front = null;
    this.rear = null;
    this.size = 0; // 노드 수
  }
  enqueue(item) {
    const newNode = new Node(item);
    if (this.isEmpty()) {
      this.front = newNode;
      this.rear = newNode;
    } else {
      this.rear.next = newNode;
      this.rear = newNode;
    }
    this.size++;
  }
  dequeue() {
    if (this.isEmpty()) {
      return null;
    }
    const removedNode = this.front;
    this.front = this.front.next;
    if (this.front === null) {
      this.rear = null;
    }
    this.size--;
    return removedNode.data;
  }

  isEmpty() {
    return this.size === 0;
  }
}

🧩 큐 관련 코테 문제

🎮 🃏 [프로그래머스/159994] 카드 뭉치

  • 문제 요약:
    1. 문자열로 이루어진 배열 cards1, cards2와 원하는 단어 배열 goal이 매개변수로 주어진다.
    2. 각 카드 배열의 앞에서부터 순차적으로만 뽑을 수 있다.
    3. goal과 문자열을 만들 수 있다면 "Yes"를, 만들 수 없다면 "No"를 반환한다.
  • 문제의 핵심은 순차적으로 큐의 개념이 필요해요. for문으로 card1card2의 첫 번째 카드가 타겟 문자열과 같으면 해당 큐를 dequeue하면서 goal과 동일한 문자열이 될 수 있는지 확인합니다.
  • 여기서는 이미 배열이 주어졌기 때문에 주어진 배열을 큐처럼 사용해요. 또한 shift()O(n)이므로 인덱스를 증가시키는 방식으로 dequeue를 대체했어요. ( -> O(1))
function solution(cards1, cards2, goal) {
  let j = 0,
    k = 0;
  for (let i = 0; i < goal.length; i++) {
    if (cards1[j] === goal[i]) {
      j++;
    } else if (cards2[k] === goal[i]) {
      k++;
    } else {
      return "No";
    }
  }

  return "Yes";
}

[프로그래머스/1844] 게임 맵 최단거리

  • 최단 거리를 구하는 BFS 문제에서도 큐가 이용돼요.
  • 문제 요약:
    게임 맵 최단거리 그림 설명
    게임 맵 최단거리 그림 설명2
1.  n x m 크기의 게임 맵(`maps`)이 주어지고, `0`은 벽, `1`은 길이다.
2.  캐릭터는 시작엄 **(1,1)**에서 출발하여 도착 지점까지 지나가는 칸의 **최솟값**을 반환한다.
3.  도착 지점에 도달 불가능하면 -1를 반환한다.
  • 왜 큐를 사용할까?:
    • BFS는 항상 가까운 칸부터 차례대로 탐색해요. 따라서 먼저 들어온 좌표를 먼저 꺼낼 수 있는 자료구조, 즉 큐가 필요합니다. 따라서 도착 지점을 처음 만나는 순간이 곧 최단 거리가 돼요.
function solution(maps) {
  const dirs = [
    [1, 0],
    [-1, 0],
    [0, 1],
    [0, -1],
  ];
  const row = maps.length;
  const col = maps[0].length;
  const visited = Array(row)
    .fill(0)
    .map((e) => Array(col).fill(false));

  function canGo(r, c) {
    if (r < 0 || c < 0 || r >= row || c >= col) return false;
    if (maps[r][c] === 0 || visited[r][c]) return false;
    return true;
  }

  function bfs(r, c) {
    const q = [[r, c, 1]];
    visited[r][c] = true;

    while (q.length) {
      let [r, c, len] = q.shift();
      if (r === row - 1 && c === col - 1) return len;
      for (const [dr, dc] of dirs) {
        let curR = r + dr;
        let curC = c + dc;

        if (canGo(curR, curC)) {
          visited[curR][curC] = true;
          q.push([curR, curC, len + 1]);
        }
      }
    }
    return -1;
  }

  return bfs(0, 0);
}

🔄 원형 큐 & ⭐ 우선순위 큐

  • 원형 큐: 선형 큐의 메모리 낭비 문제를 해결했어요. frontrear가 순회하기 때문에 비어진 공간을 재사용할 수 있어요.
    • 하지만 코딩 테스트에서는 js에서 제공하는 배열로도 충분히 커버가 가능하기 때문에 원형 큐를 사용할 필요는 없다고 한다.
  • 우선 순위 큐: 순서가 아니라 우선순위가 높으면 먼저 처리되는 구조로, 선형 큐와 다르게 heap으로 구현해요.

📚 참고 자료

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/12   »
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
글 보관함