자료를 보관할 수 있는 (선형)구조
단, 넣을때는 한쪽 끝에서 밀어 넣어야 하고(인큐 ebqueue) 꺼낼때에는 반대쪽에서 뽑아 꺼내야 함(디큐 dequeue)
[Q] |
---|
- |
- |
- |
[Q] |
---|
- |
B |
A |
[Q] |
---|
- |
- |
B |
r2 = Q.dequeue() → B
[Q] |
---|
- |
- |
- |
class ArrayQueue:
def __init__(self):
self.data = []
def size(self):
return len(self.data)
def isEmpty(self):
return self.size() == 0
def enqueue(self.item):
self.data.append(item)
def dequeue(self):
return self.data.pop(0) # 0번 인덱스 리턴
def peek(self):
return self.data[0]
연산 | 복잡도 |
---|---|
size( ) | O(1) |
isEmpty( ) | O(1) |
enqueue( ) | O(1) |
dequeue( ) | O(n) |
peek( ) | O(1) |
20 | 37 | 58 | 65 | 72 | 91 |
---|
맨 앞에 있는 20을 꺼내려고 할 때,
37 | 58 | 65 | 72 | 91 | - |
---|
원소를 하나하나 당겨야 해서 배열의 길이가 길면 오래걸림
정해진 개수의 저장 공간을 빙 돌려가며 이용
→ front와 rear을 적절히 계산하여 배열을 환형으로 재활용
rear : 데이터를 집어넣는 쪽
front : 데이터를 꺼내는 쪽
길이 n = 6인 리스트 확보
- | - | - | - | - | - |
---|
Q.enqueue(A)
A | - | - | - | - | - |
---|---|---|---|---|---|
rear | - | - | - | - | - |
Q.enqueue(B)
A | B | - | - | - | - |
---|---|---|---|---|---|
- | rear | - | - | - | - |
Q.enqueu(C)
A | B | C | - | - | - |
---|---|---|---|---|---|
- | - | rear | - | - | - |
Q.enqueue(D)
A | B | C | D | - | - |
---|---|---|---|---|---|
- | - | - | rear | - | - |
r1 = Q.dequeue( ) → A
B | C | D | - | - | |
---|---|---|---|---|---|
front | - | - | rear | - | - |
r2 = Q.dequeue( ) → B
C | D | - | - | ||
---|---|---|---|---|---|
- | front | - | rear | - | - |
Q.enqueue(E)
C | D | E | - | ||
---|---|---|---|---|---|
- | front | - | - | rear | - |
Q.enqueue(F)
C | D | E | F | ||
---|---|---|---|---|---|
- | front | - | - | - | rear |
Q.enqueue(G) 이때, 환형 큐이기 때문에 rear가 다시 처음으로 돌아감
G | C | D | E | F | |
---|---|---|---|---|---|
rear | - | front | - | - | - |
r3 = Q.dequeue( ) → C
G | D | E | F | ||
---|---|---|---|---|---|
rear | - | front | - | - | - |
class CircularQueue:
def __init__(self,n):
self.maxCount = n
self.data = [None] * n
self.count = 0
self.front = -1
self.rear = -1
def size(self):
return self.count
def isEmpty(self):
return self.count == 0
def isFull(self):
return self.count == self.maxCount
def enqueue(self, x):
if self.isFull():
raise IndexError('Queue full')
self.rear = (self.rear + 1) % self.maxCount
self.data[self.rear] = x
self.count += 1
def dequeue(self):
if self.isEmpty():
raise indexError('Queue empty')
self.front = (self.front + 1) % self.maxCount
x = self.data[self.front]
self.count -= 1
return x
def peek(self):
if self.isEmpty:
raise IndexError('Queue empty')
return self.data[(self.front + 1) % self.maxCount]
큐가 FIFO방식을 따르지 않고 원소들의 우선순위에 따라 큐에서 빠져나오는 방식
→ 1번이 더 유리. 2번은 모든 데이터들을 하나하나 살펴봐야 하기때문에 큐의 길이에 비례하는 시간이 걸림
→ 시간적으로 볼때는 연결리스트가 더 유리 but 선형 배열이 메모리 덜 소요
from doublylinkedlist import Node, DoublyLinkedList
class PriorityQueue:
def __init__(self,x):
self.queue = DoublyLinkedList()
def enqueue(self,x):
newNode = Node(x)
curr = self.queue.head
while curr.next != self.queue.tail and x < curr.next.data:
curr = curr.next
self.queue.insertAfter(curr, newNode)
def dequeue(self):
return self.queue.popAt(self.queue.getLength())
def peek(self):
return self.queue.getAt(self.queue.getLength()).data