큐(Queue)

0. μš”μ•½

class Node {
  constructor(data) {
    this.data = data;
    this.next = null;
  }
}

class Queue {
  constructor(array) {
    this.front = null;
    this.rear = null;
    this.size = 0;
    if (array) {
      array.forEach((item) => {
        this.enqueue(item);
      });
    }
  }

  // 큐가 λΉ„μ–΄μžˆλŠ”μ§€ ν™•μΈν•˜κΈ°
  isEmpty() {
    return !Boolean(this.size);
  }

  // 큐에 μ›μ†Œ μΆ”κ°€ν•˜κΈ°
  enqueue(data) {
    const node = new Node(data);
    if (this.isEmpty()) this.front = node;
    else this.rear.next = node;
    this.rear = node;
    this.size++;
  }

  // 큐에 μ›μ†Œ μ œκ±°ν•˜κΈ°
  dequeue() {
    const frontQueue = this.front;
    if (this.isEmpty()) return;
    this.front = this.front.next;
    this.size--;
    if (this.size === 0) this.rear = null;
    return frontQueue;
  }

  // 큐에 ν•΄λ‹Ή μ›μ†Œκ°€ μ‘΄μž¬ν•˜λŠ”μ§€ ν™•μΈν•˜μ—¬ μ‘΄μž¬ν•˜λ©΄ ν•΄λ‹Ή μ›μ†Œλ₯Ό λ°˜ν™˜ν•˜κΈ°
  contains(data) {
    let cur = this.front;
    let node;
    while (!node) {
      if (!cur) return;
      if (cur.data === data) node = cur;
      else cur = cur.next;
    }
    return node;
  }

  // 큐의 λͺ¨λ“  μ›μ†Œ 좜λ ₯ν•˜κΈ°
  display() {
    let cur = this.front;
    let index = 0;
    while (index < this.size) {
      console.log(`${index}. ${cur.data}`);
      cur = cur.next;
      index++;
    }
  }
}

1. κ°œμš”

JAVA λ˜λŠ” 파이썬 같은 경우 λ‚΄μž₯ λΌμ΄λΈŒλŸ¬λ¦¬μ— 큐λ₯Ό μ œκ³΅ν•˜κ³  μžˆμ§€λ§Œ μžλ°”μŠ€ν¬λ¦½νŠΈ κ²½μš°μ—” κ·Έλ ‡μ§€ μ•Šλ‹€. κ·Έλž˜μ„œ μžλ°”μŠ€ν¬λ¦½νŠΈμ—μ„œ 큐λ₯Ό μ‚¬μš©ν•˜κΈ° μœ„ν•΄μ„œλŠ” 직접 큐λ₯Ό μž‘μ„±ν•΄μ•Όν•œλ‹€.

사싀 μžλ°”μŠ€ν¬λ¦½νŠΈμ—μ„œ 큐λ₯Ό μ‚¬μš©ν•˜μ§€ μ•Šκ³  배열을 μ΄μš©ν•˜μ—¬ 큐의 κΈ°λŠ₯을 μ‚¬μš©ν•  수 μžˆλ‹€. Array.shift() λ©”μ„œλ“œμ™€ Array.pop() λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•˜λ©΄ λœλ‹€. ν•˜μ§€λ§Œ μ΄λ ‡κ²Œ 되면 μ‹œκ°„λ³΅μž‘λ„μ—μ„œ 큐와 큰 차이λ₯Ό 보이게 λœλ‹€. νμ—μ„œμ˜ μ›μ†Œ μ œκ±°λŠ” μ‹œκ°„λ³΅μž‘λ„ O(1)λ₯Ό λ”°λ₯΄κ²Œ λ˜λŠ”λ° λ°°μ—΄μ—μ„œμ˜ Array.shift() λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•œ μ›μ†Œ μ œκ±°λŠ” μ‹œκ°„λ³΅μžλ„ O(n)λ₯Ό λ”°λ₯΄κ²Œ 되기 λ•Œλ¬Έμ΄λ‹€.

Array.shift() λ©”μ„œλ“œμ˜ λ‚΄λΆ€ λ‘œμ§μ€ λ‹€μŒκ³Ό κ°™λ‹€.

  • λ°°μ—΄μ˜ 첫 번째 μ›μ†Œμ— μ ‘κ·Όν•˜μ—¬ ν•΄λ‹Ή 값을 λ°˜ν™˜ν•˜κ³  λ°°μ—΄μ—μ„œ 제거

  • κΈ°μ‘΄ λ°°μ—΄μ—μ„œ 첫 번째 μ›μ†Œμ˜ 값은 μ‚¬λΌμ‘Œμ§€λ§Œ 곡간은 μ°¨μ§€ν•˜κ³  있음

  • Array.shift() λ©”μ„œλ“œλŠ” κ³„μ†ν•΄μ„œ 첫 번째 μ›μ†Œμ— μ ‘κ·Όν•  μ˜ˆμ •

  • λ”°λΌμ„œ λ‚˜λ¨Έμ§€ λ°°μ—΄μ˜ μ›μ†Œλ“€μ„ μ•žμœΌλ‘œ ν•œ μΉΈμ”© λ‹Ήκ²¨μ£ΌλŠ” κ³Όμ • ν•„μš”

즉 λ§ˆμ§€λ§‰μ˜ 과정에 λŒ€ν•œ 연산이 μΆ”κ°€μ μœΌλ‘œ μš”κ΅¬λœλ‹€. μ΄λŸ¬ν•œ 좔가적인 μ—°μ‚°μœΌλ‘œ 인해 μ½”λ”© ν…ŒμŠ€νŠΈ λ¬Έμ œμ—μ„œ λ°μ΄ν„°μ˜ 양이 맀우 큰 경우, μ‹œκ°„ λ³΅μž‘λ„λ₯Ό 맀우 μ„Έμ„Έν•˜κ²Œ 관리해야 ν•˜λŠ” κ²½μš°μ—λŠ” λ°°μ—΄λ‘œ μ΄μš©ν•˜μ—¬ 문제λ₯Ό ν’€κ²Œ λœλ‹€λ©΄ 톡과할 수 μ—†λŠ” κ²½μš°κ°€ μžˆμ„ 수 μžˆλ‹€. 이런 경우 큐λ₯Ό μ΄μš©ν•˜μ—¬ 더 λΉ λ₯Έ μ‹œκ°„ λ³΅μž‘λ„λ‘œ λ¬Έμ œμ— μ ‘κ·Όν•œλ‹€λ©΄ 톡과할 수 μžˆλŠ” ν™•λ₯ μ΄ 올라갈 것이닀.

μ°Έκ³ ν•  λ§Œν•œ μ½”λ”© ν…ŒμŠ€νŠΈ 문제


2. νλž€?

FIFO(First in, First out) μ›μΉ™μœΌλ‘œ λ§Œλ“€μ–΄μ§„ 자료ꡬ쑰둜 μžλ°”μŠ€ν¬λ¦½νŠΈ μ—”μ§„μ—μ„œ 비동기 ν•¨μˆ˜ μ‹€ν–‰μ‹œ μ½œλ°±λ“€μ΄ λŒ€κΈ°μ—΄λ‘œ λ“€μ–΄μ˜€λŠ” Task queueκ°€ λŒ€ν‘œμ μΈ μ˜ˆμ΄λ‹€.

Queue

νλŠ” λ†€μ΄κ³΅μ›μ—μ„œ λ¨Όμ € 온 μ‚¬λžŒμ΄ 놀이기ꡬλ₯Ό λ¨Όμ € νƒ€λŠ” 것과 λ§ˆμ°¬κ°€μ§€λ‘œ λ¨Όμ € 넣은 데이터가 λ¨Όμ € λ‚˜κ°„λ‹€. 큐의 κ°€μž₯ 첫 번째 μ›μ†Œλ₯Ό front, 끝 μ›μ†Œλ₯Ό rear둜 λΆ€λ₯΄λ©° λ°μ΄ν„°μ˜ 접근방법은 front와 rear둜만 κ°€λŠ₯ν•˜λ‹€. λ˜ν•œ rearμ—μ„œλŠ” μ‚½μž… μ—°μ‚°λ§Œ μΌμ–΄λ‚˜κ³ , front μ—μ„œλŠ” μ‚­μ œ μ—°μ‚°λ§Œ μΌμ–΄λ‚œλ‹€.

νμ—μ„œ μ‚¬μš©λ˜λŠ” λ©”μ„œλ“œλŠ” μ•„λž˜μ™€ 같이 μ •μ˜ν•  수 μžˆλ‹€.

  • dequeue: frontλ₯Ό μ œκ±°ν•˜κ³  λ°˜ν™˜ν•œλ‹€.

  • enqueue: 큐에 μ›μ†Œλ₯Ό μΆ”κ°€ν•œλ‹€. μ΄λ•Œ ν•΄λ‹Ή μ›μ†ŒλŠ” rearκ°€ λœλ‹€.

  • contains: ν•΄λ‹Ή μ›μ†Œκ°€ 큐에 μ‘΄μž¬ν•˜λŠ”μ§€ ν™•μΈν•˜μ—¬ μ‘΄μž¬ν•˜λ©΄ ν•΄λ‹Ή μ›μ†Œλ₯Ό λ°˜ν™˜ν•œλ‹€.


3. μ—°κ²° 리슀트둜 큐 κ΅¬ν˜„ν•˜κΈ°

μ—°κ²° 리슀트λ₯Ό 톡해 큐λ₯Ό κ΅¬ν˜„ν•œλ‹€.


3-1. λ…Έλ“œμ™€ 큐의 κΈ°λ³Έ ꡬ쑰

λ…Έλ“œμ™€ 큐의 κΈ°λ³Έ κ΅¬μ‘°λŠ” μ—°κ²° λ¦¬μŠ€νŠΈμ—μ„œ λ‹€λ£¨μ—ˆλ˜ λ‚΄μš©κ³Ό κ°™λ‹€.


3-2. 큐가 λΉ„μ–΄μžˆλŠ”μ§€ ν™•μΈν•˜κΈ°

μžλ°”μŠ€ν¬λ¦½νŠΈμ—μ„œ 숫자 0은 λΆˆλ¦¬μ–ΈμœΌλ‘œ λ³€ν™˜ν–ˆμ„ λ•Œ falseλ₯Ό 가리킨닀. κ·Έλ ‡κΈ° λ•Œλ¬Έμ— μ•žμ— !λ₯Ό λΆ™μ—¬ ture둜 λ°”κΎΈμ–΄ isEmpty ν•¨μˆ˜κ°€ 큐에 μ›μ†Œκ°€ 없을 경우 trueλ₯Ό λ°˜ν™˜ν•˜κ²Œ ν•œλ‹€.


3-3. 큐에 μ›μ†Œ μΆ”κ°€ν•˜κΈ°

  • 큐에 μ›μ†Œκ°€ 없을 경우 μƒˆλ‘­κ²Œ μƒμ„±λœ Nodeλ₯Ό fornt둜 μ§€μ •ν•œλ‹€.

  • 큐에 μ›μ†Œκ°€ μžˆμ„ 경우 κΈ°μ‘΄ 큐의 rear.nextλ₯Ό μƒˆλ‘­κ²Œ μƒμ„±λœ Node둜 μ§€μ •ν•œλ‹€.

    front와 rear도 Node이닀. κ·Έλž˜μ„œ data 속성과 next 속성을 κ°€μ§„λ‹€.

  • λ§ˆμ§€λ§‰μœΌλ‘œ μƒˆλ‘­κ²Œ μƒμ„±λœ Nodeλ₯Ό rear둜 λ°”κΎΈλ©΄ λœλ‹€.(size도 ν•˜λ‚˜ 올리자.)


3-4. 큐에 μ›μ†Œ μ œκ±°ν•˜κΈ°

  • 큐의 frontλ₯Ό frontQueue에 μ €μž₯ν•œλ‹€.

  • 큐가 λΉ„μ–΄μžˆλ‹€λ©΄ 아무것도 λ¦¬ν„΄ν•˜μ§€ μ•Šκ³  ν•¨μˆ˜λ₯Ό μ’…λ£Œν•œλ‹€.

  • κΈ°μ‘΄ 큐의 frontλ₯Ό front.next둜 μ§€μ •ν•œλ‹€.

  • sizeλ₯Ό ν•˜λ‚˜ κ°μ†Œμ‹œν‚¨λ‹€.

  • λ§Œμ•½ sizeκ°€ 0이 되면 큐에 μ›μ†Œκ°€ μ—†λŠ” κ²ƒμ΄λ―€λ‘œ rearλ₯Ό null둜 λ°”κΎΈμ–΄μ•Ό ν•œλ‹€.

  • λ§ˆμ§€λ§‰μœΌλ‘œ νμ—μ„œ μ œκ±°ν•œ μ›μ†ŒμΈ frontQueueλ₯Ό λ°˜ν™˜ν•œλ‹€.


3-5. 큐에 ν•΄λ‹Ή μ›μ†Œκ°€ μ‘΄μž¬ν•˜λŠ”μ§€ ν™•μΈν•˜μ—¬ μ‘΄μž¬ν•˜λ©΄ ν•΄λ‹Ή μ›μ†Œλ₯Ό λ°˜ν™˜ν•˜κΈ°

  • curλ₯Ό 큐의 front둜 μ§€μ •ν•œλ‹€.

  • λ¦¬ν„΄ν•˜κ²Œ 될 λ³€μˆ˜ nodeλ₯Ό μ„ μ–Έν•œλ‹€.

  • node에 큐의 μ›μ†Œκ°€ 할당될 λ•Œ κΉŒμ§€ λ°˜λ³΅λ¬Έμ„ μ‹€ν–‰ν•œλ‹€.

  • λ§Œμ•½ cur이 null이라면 ν•΄λ‹Ή μ›μ†Œκ°€ μ—†κΈ° λ•Œλ¬Έμ— 아무것도 λ°˜ν™˜ν•˜μ§€ μ•Šκ³  ν•¨μˆ˜λ₯Ό μ’…λ£Œν•œλ‹€.

  • cur이 null이 λœλ‹€λŠ” 것은 큐의 λͺ¨λ“  μ›μ†Œλ₯Ό ν™•μΈν–ˆλ‹€λŠ” 것이닀.

  • cur.data와 contains ν•¨μˆ˜μ˜ 인자둜 받은 dataκ°€ κ°™λ‹€λ©΄ node에 curλ₯Ό ν• λ‹Ήν•œλ‹€.

  • node에 curλ₯Ό ν• λ‹Ήν•˜κ²Œ 되면 nodeλŠ” null이 μ•„λ‹ˆκΈ° λ•Œλ¬Έμ— λ°˜λ³΅λ¬Έμ€ 더 이상 μ‹€ν–‰λ˜μ§€ μ•ŠλŠ”λ‹€.

  • ν•˜μ§€λ§Œ κ°™μ§€ μ•Šλ‹€λ©΄ curλ₯Ό cur.next둜 λ°”κΎΈμ–΄ λ°˜λ³΅λ¬Έμ„ 계속 μ‹€ν–‰ν•œλ‹€.


3-6. 큐의 λͺ¨λ“  μ›μ†Œ 좜λ ₯ν•˜κΈ°


3-7. 배열을 λ„˜κ²¨ 큐 μƒμ„±ν•˜κΈ°

  • constructor ν•¨μˆ˜λ₯Ό μœ„μ™€ 같이 μˆ˜μ •ν•˜μ—¬ μƒˆλ‘œμš΄ 큐λ₯Ό λ§Œλ“€ λ•Œ arrayκ°€ μ „λ‹¬λ˜λ©΄ enqueue ν•¨μˆ˜κ°€ μ‹€ν–‰λ˜κ²Œ ν•œλ‹€.

  • Array.forEach() λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•˜μ—¬ λ°°μ—΄μ˜ λͺ¨λ“  μš”μ†Œλ₯Ό 큐의 μ›μ†Œλ‘œ λ„£λŠ”λ‹€.(μ•žμ—μ„œ λΆ€ν„° μˆœμ„œλŒ€λ‘œ)


4. 큐의 μ‹œκ°„ λ³΅μž‘λ„

  • enqueue(μΆ”κ°€): 큐에 데이터λ₯Ό μΆ”κ°€ν•˜λŠ” 것은 큐의 맨 λ’€ μ›μ†Œ(rear)에 ν•˜λ‚˜λ₯Ό μΆ”κ°€ν•˜λ©΄ λœλ‹€. 큐에 무수히 λ§Žμ€ 데이터가 μžˆλ”λΌλ„ ν•˜λ‚˜μ˜ 데이터 μ‚½μž…μ€ ν•œ 번이기 λ•Œλ¬Έμ— μ‹œκ°„ λ³΅μž‘λ„λŠ” O(1)이 λœλ‹€.

  • dequeue(μ‚­μ œ): FIFO에 따라 데이터가 μ‚­μ œλ  λ•Œ 큐의 맨 μ•ž μ›μ†Œ(front)κ°€ μ‚­μ œλ˜λŠ” κ²ƒμ΄λ―€λ‘œ 큐의 크기에 상관없이 μ‹œκ°„ λ³΅μž‘λ„λŠ” O(1)λ₯Ό κ°€μ§€κ²Œ λœλ‹€.

  • contains(μ ‘κ·Όκ³Ό 검색): 큐의 첫 번째 μ›μ†Œμ˜ 접근은 μ‹œκ°„λ³΅μž‘λ„ O(1)λ₯Ό κ°€μ§„λ‹€. ν•˜μ§€λ§Œ 큐의 μ›μ†Œ 접근은 큐의 맨 μ•ž μ›μ†Œ(front)μ—μ„œλ§Œ κ°€λŠ₯ν•˜κΈ° λ•Œλ¬Έμ— n번째 μ›μ†Œμ˜ 접근은 첫 번째 μ›μ†Œ(front)λΆ€ν„° μˆœνšŒν•˜λ―€λ‘œ μ‹œκ°„ λ³΅μž‘λ„λŠ” O(n)λ₯Ό κ°€μ§€κ²Œ λœλ‹€.

Big-O (μ‹œκ°„λ³΅μž‘λ„)
μ‚½μž…
μ‚­μ œ
첫 번째 μ ‘κ·Ό
n번째 μ ‘κ·Ό
검색

큐 (Queue)

O(1)

O(1)

O(1)

O(n)

O(n)


5. Conclusion

큐λ₯Ό μžλ°”μŠ€ν¬λ¦½νŠΈλ‘œ κ΅¬ν˜„ ν•΄λ³΄λ©΄μ„œ μ–΄λ–€ μžλ£Œκ΅¬μ‘°μΈμ§€ κ³΅λΆ€ν•΄λ³΄μ•˜λ‹€. ν™•μ‹€νžˆ λ°°μ—΄κ³ΌλŠ” λ‹€λ₯Έ νŠΉμ§•μ΄ μžˆλ‹€. μ›μ†Œμ˜ μΆ”κ°€, μ‚­μ œλŠ” λΉ λ₯΄μ§€λ§Œ μ›μ†Œμ— μ ‘κ·Ό, 검색은 느리기 λ•Œλ¬Έμ— 상황에 λ§žλŠ” ν•„μš”ν•œ 자료ꡬ쑰λ₯Ό 잘 선택을 ν•΄μ•Όκ² λ‹€. 이전에 μ½”λ”© ν…ŒμŠ€νŠΈ 곡뢀λ₯Ό ν•˜λ©΄μ„œ ν’€μ—ˆλ˜ 문제λ₯Ό 쑰금 μˆ˜μ •ν•˜μ˜€λ‹€. κ·Έ μ΄μœ λŠ” κ·Έ 땐 λ‹¨μˆœνžˆ λΈ”λ‘œκ·Έμ— μžˆλŠ” 큐 μƒμ„±ν•˜λŠ” 클래슀λ₯Ό 볡사뢙여 λ„£κΈ°λ₯Ό ν–ˆκΈ° λ•Œλ¬Έμ΄λ‹€. λ‚΄κ°€ 슀슀둜 λ§Œλ“ (λ¬Όλ‘  λΈ”λ‘œκ·Έμ˜ νž˜μ„ 빌린긴 ν–ˆμ§€λ§Œ..) 큐 클래슀λ₯Ό μ‚¬μš©ν•˜κ³  λ¬Έμ œλ„ 잘 ν†΅κ³Όλ˜λŠ” 것을 λ³΄λ‹ˆ 재밌고 λΏŒλ“―ν•˜λ‹€.


μ°Έκ³ 

[자료ꡬ쑰] JS둜 κ΅¬ν˜„ν•˜λŠ” 큐 (Queue) [μ•Œκ³ λ¦¬μ¦˜, 자료ꡬ쑰] μžλ°”μŠ€ν¬λ¦½νŠΈλ‘œ 큐(Queue)κ΅¬ν˜„ν•˜κΈ° (+κ°œλ…μ΄ν•΄)


πŸ“… 2022-09-02

Last updated