콘텐츠로 건너뛰기

큐와 덱

큐 (Queue)

  • 가장 먼저 들어간 자료가 가장 먼저 나오는 자료구조
  • 먼저 들어온 데이터가 먼저 나가는 선입선출(FIFO: First-In First-Out)의 특성을 갖는 자료구조

후단 (rear) vs 전단 (front)

  • 후단: 삽입이 일어나는 곳
  • 전단: 삭제가 일어나는 곳

큐의 사용 예제

  • 컴퓨터의 빠른 CPU와 속도가 상대적으로 느린 주변장치(프린터)들 사이의 시간이나 속도 차이를 극복하기 위한 임시 기억 장치로 사용된다.

큐의 연산

  • enqueue(e): 새로운 요소 e를 큐의 맨 뒤에 추가; 포화 상태인 경우 오버플로 발생.
  • dequeue(): 큐의 맨 앞에 있는 요소를 꺼내서 반환; 공백 상태인 경우 언더플로 발생.
  • isEmpty(): 큐가 비어있는지 검사
  • isFull(): 큐가 가득 차있는지 검사
  • peek(): 큐의 맨 앞에 있는 요소를 삭제하지 않고 반환
  • size(): 큐에 들어있는 전체 요소의 수를 반환

선형 큐

  • 용령이 5인 큐에 A~E까지 가득차있고 2번의 삭제를 순서대로 수행헀다.
  • 여기서 더 삽입하려면, 큐의 앞부분에 공간이 있는데로 rear인 후단을 증가시킬 수 없으므로 삽입 불가능.
  • 따라서, 큐의 요소들을 모두 최대한 앞으로 옮겨, 후단에 공간을 확보한 다음 삽입해야된다.
  • 동작을 이해하기에는 쉬우나, 요소들의 이동이 필요하므로 효율적이지 않다.

원형 큐

  • 인덱스인 rear 후단과 front 전단을 원형으로 회전시키는 개념
  • 이를 테면, enqueue([요소])가 호출되면 rear 후단을 시계 방향으로 1칸 회전시키고 그 위치에 [요소]를 저장하는 것.
  • 시계방향의 회전 구현: front나 rear가 계속 증가하다가 용량이 같아지면 인덱스 0으로 만들기
  • 전단 회전: front ← (front+1) % capacity
  • 후단 회전: rear ← (rear+1) % capacity

링 버퍼(ring buffer)

  • 오래된 자료를 버리고 항상 최근의 자료를 유지하는 용도로 사용.
  • 이를 테면, 최대 7개의 요소를 저장할 수 있는 원형 큐에 7개 이상의 자료들이 연속적으로 입력되었을 때,
    가장 최근에 들어온 7개만 저장되도록 하고 오래된 데이터는 버리는 것.
  • 기존의 원형인 큐에서는 포화상태일시, 산입연산을 추가로 수행하면 오버플로가 발생하나
    링 버퍼에서는 원형 큐의 enqueue 함수 작동방식을 약간 수정하여 포화 상태와 상관없이 항상 삽입 가능.
  • 즉, 가장 오래된 데이터를 삭제해서 큐를 계속 포화 상태로 유지.
  • 프로세스
  1. 공백 상태 (capacity=8)
  2. 공백 상태에서 7개의 요소를 삽입하면 포화 상태가 됨
  3. 포화 상태에서 새로운 데이터 7을 삽입하면 가장 오래된 요소 0이 삭제됨
  4. 같은 방법으로 8을 삽입하게 된다면, 가장 오래된 요소 1이 삭제됨

덱 (Deque)

  • double-ended queue
  • 전단과 후단에서 모두 삽입과 삭제 가능한 큐
  • 그러나 여전히 중간에 삽입하거나 삭제하는 것은 허용하지 않음

덱의 연산

  • addFront(e): 새로운 요소 e를 전단에 추가
  • addRear(e): 새로운 요소 e를 후단에 추가
  • deleteFront(): 덱의 전단 요소를 꺼내서 반환
  • deleteRear(): 덱의 후단 요소를 꺼내서 반환
  • getFront(): 덱의 전단 요소를 삭제하지 않고 반환
  • getRear(): 덱의 후단 요소를 삭제하지 않고 반환
  • isEmpty(): 덱이 비어있는지 검사
  • isFull(): 덱이 가득 차있는지 검사
  • size(): 덱에 들어있는 전체 요소의 수를 반환

덱의 연산 vs 스택의 연산

  • 덱의 addRear, deleteFront, getFront 연산은 각각 큐의 enqueue, dequeue, peek 연산과 동일하다
  • 덱의 후단(rear)을 스택의 상단(top)으로 사용한다면,
    덱의 addRear, deleteRear, getRear 연산은 스택의 push, pop, peek 연산과 정확히 동일하다.

덱의 deleteRear, addFront 연산

  • 원형 큐의 enqueue나 dequeue 연산과는 달리 인덱스를 하나씩 줄여야하는데,
    이것은 반시계 방향 회전을 의미한다.
  • 이를 위한 인덱스 처리는 나머지 연산을 이용해 간결히 가능
  • 전단 회전(반시계 방향): front ← (front-1+capacity) % capacity
  • 후단 회전(반시계 방향): rear ← (rear-1+capacity) % capacity

답글 남기기