nathan_H
[자료구조] Queue 의 특징 및 활용예제 본문

큐는 스택 자료구조와 달리 FIFO (First-In First-Out)- 선입 선출 특징으로
- 넣을 때에는 한 쪽 끝에서 밀어 넣어야 한다. -> enqueue 연산
- 꺼낼 때에는 반대 쪽에서 뽑아 꺼내야하는 제약 -> dequeue 연산
즉 enqueue로 삽입된 원소가 가장 나중에 dequeue로 빠져나온다는 것이다.
추상적 자료구조 구현
method
- size() - 현재 큐에 들어 있는 데이터 원소의 수 O(1)
- isEmpty() - 현재 큐가 비어 있는지 판단 O(1)
- enqueue(x) - 데이터 원소 큐에 추가 O(1)
- dequeue - 큐에 맨 앞에 저장된 데이터 원소 제기 or 반환 O(n)
- peek() - 큐의 맨앞에 저장된 데이터 원소 반환(제거 x) O(1)
- dequeue 시간 복잡도 - 20, 37, 58, 65, 72, 91
> 맨앞에 요소를 뺌으로 인덱스가 순차적으로 앞으도 당겨와서 시간 복잡도가 O(n) 리스트가 길면 길수록 오래 걸린다.
Array로 구현
-> Python list Built-in method
class ArrayQueue: def __init__(self): self.data = [] def is_Empty(self): return if not self.data def size(self): return len(self.data) def enqueue(self, item): self.data.append(item) def dequeue(self): return self.data.pop(0) def peek(self): return self.data[0]
DoublyLinkedList로 구현
class LinkdeListQueue: def __init__(self): self.data = DoublyLinkedList() def is_Empty(self): return self.data.getLength == 0 def size(self): return self.data.getLength() def enqueue(self, item): newNode = Node(item) self.data.insertAt(self.data.nodeCount + 1, newNode) def dequeue(self): return self.data.popAt(1) def peek(self): return self.data.getAt(1).data
선행 배열 or 연결 리스트중 머가 더 유리할까?
- 시간적인 측면은 연결 리스트가 유리.
- 메모리 측면에서는 선형 배열이 유리함.
시간을 우선순위를 두고 채택하는 경우가 많음.
큐 활용
-
자료를 생성하는 작업과 그 자료를 이용하는 작업이 비동기적으로 일어나는 경우
-
자료를 생성하는 작업과 그 자료를 이용하는 작업이 양쪽 다 여러 곳에서 이용하는 경우.
consumer <- product <- producer
consumer <- product <- producer1, producer2
consumer1, consumer2 <- product <- producer -
자료를 처리하여 새로운 자료를 생성하고, 나중에 그 자료를 또 처리해야 하는 작업의 경우
-
환형 큐
- 정해진 개수의 저장 공간을 빙 돌려가며 이용.
- 큐 길이를 기억하고 있어야 한다. (정해진 개수)
- front, rear -
priority queue
→ 큐가 FIFO 방식을 따르지 않고 원소드르이 우선순위에 따라 큐에서 빠져나오는 방식.
활용 예 - 운영체제의 cpu 스케쥴러
방식 1. enqueue 할 때 우선순위 순서를 유지하도록
방식 2. dequeue 할 때 우선순위 높은 것을 선택 → 어느 것이 유리 할까?
- 1번이 유리함. (무작위로 들어 갔을 때 dequeue 할때 원소를 다 찾아야함으로 오래 걸림)
환형 큐 코드 구현
class CircularQueue: def __init__(self, counts): self.data = [None] * counts self.front = -1 self.rear = -1 self.maxCount = counts self.count = 0 def is_Empty(self): return self.count == 0 def size(self): return self.count def isFull(self): return self.maxCount == self.count def enqueue(self, item): if self.isFull(): raise IndexError('Queue full') self.rear = (self.rear + 1) % (self.maxCount) self.data[self.rear] = item self.count += 1 def dequeue(self): if self.is_Empty(): 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.is_Empty(): raise IndexError('Queue empty') return self.data[(self.front + 1) % (self.maxCount)]
우선순위 큐 코드 구현
# from DoublyLinkedList.DoublyLinkedList import Node, DoublyLinkedList class PriorityQueue: def __init__(self): self.queue = DoublyLinkedList() def size(self): return self.queue.getLength() def is_Empty(self): return self.queue.nodeCount == 0 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 ''' while x < curr.next.data and curr.next != self.queue.tail -> 만약 curr.next.data 가 None인 경우 TypeError: '<' not supported between instances of 'int' and 'NoneType' 하지만 while curr.next.data != None and x < curr.next.data 이런 순서로 할 경우에는 curr.next.data == None인 경우 뒤에 조건을 무시해 오류를 피해 갈 수 있다. ''' 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
'Computer Science > DataStructure' 카테고리의 다른 글
[Stack] python으로 구현한 자료구조 stack (1) | 2019.07.06 |
---|---|
양방향 연결리스트(Double LinkedList) (0) | 2019.07.04 |
연결리스트의 특징과 파이썬 코드 구현 (0) | 2019.07.02 |