Do it! 자료구조와 함께 배우는 알고리즘 입문 | 파이썬편을 읽고 작성된 글입니다.
Github Link : https://github.com/WE-Learning-CS/Data-Structure/tree/main/chap04/02
큐는 스택과 같이 데이터를 임시 저장하는 자료구조이다.
스택과는 반대로 FIFO(First In First Out)
이다. 즉, 먼저 push 된게 먼저 pop 된다.
인큐 (enqueue) : 큐에 데이터를 추가하는 작업
디큐 (dequeue) : 큐에서 데이터를 꺼내는 작업
프런트 (front) : 데이터를 꺼내는 쪽
리어 (rear) : 데이터를 집어넣는 쪽, back이라고도 함
class Queue:
def __init__(self):
self.queue = []
def isEmpty(self):
if not self.queue:
return True
else:
return False
def enqueue(self, data):
self.queue.append(data)
def dequeue(self):
if self.isEmpty():
return "Queue is Empty"
else:
dequeued = self.queue[0]
del self.queue[0]
return dequeued
def peek(self):
if self.isEmpty():
return "Queue is Empty"
return self.queue[0]
인큐 시 데이터에 우선순위를 부여하여 추가하고, 디큐 시 우선순위가 가장 높은 데이터를 꺼내는 방식.
# path : chap04/priority_queue.py
from collections import namedtuple
class PriorityQueue:
Element = namedtuple("element", ["priority", "data"])
def __init__(self):
self.queue = []
def isEmpty(self):
if not self.queue:
return True
else:
return False
def enqueue(self, priority, data):
return self.queue.append(PriorityQueue.Element(priority, data))
def dequeue(self):
if self.isEmpty():
return "Queue is Empty"
data = self.queue[0]
idx = 0
for i in range(1, len(self.queue)):
if data.priority < self.queue[i].priority:
data = self.queue[i]
idx = i
del self.queue[idx]
return data
우선순위 큐
파이썬에서 우선순위를 부여하는 큐는 heapq 모듈에서 제공한다.heap에서 data의 인큐는 heapq.heqppush(heap,data) 로 수행하고, 디큐는 heapq.heapop(heap)으로 수행한다.
링버퍼 : 배열 맨 끝의 원소 뒤에 맨 앞의 원소가 연결되는 자료 구조
출처 : https://namu.moe/w/%ED%81%90(%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0)
기존의 큐는 공간이 꽉 차게 되면 더이상 요소를 추가할 수 없다. 앞쪽에 공간이 남아있다면 동그랗게 연결해 앞쪽으로 추가할 수 있도록 재활용 가능한 큐가 링 버퍼큐(원형 큐)이다.
# path : chap04/fixed_queue.py
from typing import Any
class FixedQueue:
class Empty(Exception):
pass
class Full(Exception):
pass
def __init__(self, capacity: int) -> None:
self.no = 0 # 현재 데이터 개수
self.front = 0 # 맨 앞 원소 커서
self.rear = 0 # 맨 끝 원소 커서
self.capacity = capacity # 큐의 크기
self.que = [None] * capacity # 큐의 본체
def __len__(self) -> int:
'''큐에 있는 모든 데이터 개수를 반환'''
return self.no
def isEmpty(self) -> bool:
'''큐가 비어있는지 판단'''
return self.no <= 0
def isFull(self) -> bool:
'''큐가 가득 차 있는지 판단'''
return self.no >= self.capacity
def enqueue(self, x: Any) -> None:
'''데이터 x를 인큐'''
if self.isFull():
raise FixedQueue.Full
self.que[self.rear] = x
self.rear += 1
self.no += 1
if self.rear == self.capacity: # 큐가 가득 찰 경우
self.rear = 0
def dequeue(self) -> Any:
'''데이터를 디큐'''
if self.isEmpty():
raise FixedQueue.Empty
x = self.que[self.front]
self.front +=1
self.no -=1
if self.front == self.capacity: # 큐 배열의 한계를 넘어설경우
self.front = 0 # front값을 배열 맨 앞 인덱스인 0으로 되돌림
return x
def peek(self) -> Any:
'''큐의 맨 앞 데이터를 확인'''
if self.isEmpty():
raise FixedQueue.Empty
return self.que(self.front)
def find(self, value: Any) -> Any:
'''큐에서 value를 찾아 인덱스 반환 (없으면 -1)'''
for i in range(self.no):
idx = (i + self.front) % self.capacity
if self.que[idx] == value:
return idx
return -1
def count(self, value: Any) -> Any:
'''큐에 있는 value의 개수를 반환'''
c = 0
for i in range(self.no):
idx = (i + self.front) % self.capacity
if self.que[idx] == value:
c += 1
return c
def __contains__(self, value: Any) -> Any:
'''큐에 value가 있는지 판단'''
return self.count(value)
def clear(self) -> None:
'''큐 초기화'''
self.no = self.front = self.rear = 0
def dump(self) -> None:
'''모든 데이터를 맨 앞부터 맨 끝 순으로 출력'''
if self.isEmpty():
print("Queue is Empty")
else:
for i in range(self.no):
print(self.que[(i + self.front) % self.capacity], end='')
print()