1. 선형 큐(Linear Queue) a. 선형 큐는 말 그대로 선형 자료구조 형태를 하는 큐이다 b. 가장 앞 부분을 front, 가장 뒤 부분을 rear로 지칭한다 c. 데이터 삽입시 rear가 가리키는 위치에 추가하고 rear를 1만큼 증가시킨다 d. 데이터 삭제시 front에 위치하는 데이터를 삭제하고 front를 1만큼 증가시킨다 2. 원형 큐(Circular Queue) a. 원형 큐는 원 형태의 큐인 자료구조이다 b. 선형 큐와 동일하게 앞부분은 front, 뒤 부분을 rear로 지칭한다 c. 데이터가 비어 있을 때는 front와 rear위치가 동일하다 d. rear를 1만큼 증가시켰을 때 front와 동일하다면 데이터가 꽉 차있는 상태이다 (front%max_size == (rear+1)%max_size) e. 데이터 삽입 방법은 선형 큐와 동일하다 f. 데이터 삭제 방법은 선형 큐와 동일하다 3. 연결 리스트 큐(Linked list Queue) a. 연결 리스트를 활용한 큐 b. 큐의 길이를 유동적으로 조절할 수 있다 (오버 플로우 X) c. 선형, 원형 둘다 구현 가능하다 d. 데이터를 저장하는 노드(node)와 다음의 노드를 가리키는 링크(link)로 구성된다 e. 가장 먼저 있는 데이터를 가리키는 리스트의 머리(head)를 만들어야 한다 f. 마지막 노드의 링크가 가리키는 꼬리(tail)을 만들어야 한다 4. 우선순위 큐 (Priority Queue) a. 모든 데이터에 우선순위가 있다 b. 우선순위가 높은 데이터는 우선순위가 낮은 데이터 보다 먼저 큐에서 삭제된다 c. 두 개 이상의 데이터의 우선순위가 같으념 큐에 삽입 되어 있는 순서에 따라 삭제된다 d. 데이터를 삭제할 때 루트노드의 값을 추출하고 힙의 맨 끝의 데이터를 루트노드에 배치한다. 그 다음 맨 끝의 데이터를 삭제한다. 힙 속성에 따라 값의 위치를 변경해준다 (힙 속성이 유지될때까지 계속해서 값의 위치를 변경한다) e. 데이터를 삽입할 때 힙끝에 삽입하고 부모노드와 비교하여 힙 속성에 따라 값의 위치를 변경해준다 (힙 속성이 유지될때까지 계속해서 값의 위치를 변경한다) f. 삽입과 삭제 모두 트리의 높이 만큼 타고 올라가기 때문에 시간복잡도는 log2n이 된다
1) 선형 큐의 장단점
장점
구현이 간단하다
단점
삭제 연산을 반복하게 되면 front의 위치가 rear와 가까워지기 때문에 기존의 데이터 공간을 사용할 수 없는 문제가 발생한다 (실제로는 데이터 공간이 남아있다)
데이터 사용공간을 확보하기 위해서 삭제 연산시 원소를 삭제한 만큼 shift연산을 해야 하기 때문에 속도가 느리고 비효율적이다
2) 원형 큐의 장단점
장점
메모리 공간 활용이 용이하다 (선형 큐의 단점을 해결)
단점
큐의 크기가 제한된다
원형큐의 상태
원형큐의 삽입과 삭제
3) 연결리스트 큐의 장단점
장점
큐의 크기 제한이 없다
삽입, 삭제가 편리하다
단점
데이터 탐색이 오래 걸린다
구현이 비교적 어렵다
연결리스트 큐의 삽입과 삭제
4) 우선순위 큐의 장단점
장점
보통 힙으로 구현하기 때문에 힙의 장점인 데이터 삽입시 속도의 편차가 크지 않다는 장점이 있다 (log2n)
classCircularQueue: def__init__(self): # 큐의 앞, 뒤, 데이터 공간을 지정한다 self.front = 0 self.rear = 0 self.datas = [None] * size
defenqueue(self, data): # Enqueue 작업 수행 (삽입) # 삽입 가능한 상태인지 체크후 # 데이터를 뒤에서부터 삽입한다. 이때 rear의 인덱스를 증가시키고 해당 인덱스에 삽입한다 # 만약 rear가 최대인덱스를 넘어가면 최대 크기를 나눈 나머지 인덱스를 지정한다 ifnot self.isFull(): self.rear = (self.rear + 1) % size self.datas[self.rear] = data
defdequeue(self): # dequeue 작업 수행 (삭제) # 데이터가 비어있는지 체크후 # 데이터가 있다면 front를 옮김으로써 큐 안에 있는 데이터를 지운다 ifnot self.isEmpty(): self.front = (self.front + 1) % size self.datas[self.front] return self.datas[self.front] defpeek(self): # 데이터가 비어있지 않으면 front 다음 인덱스 안에 있는 값을 반환한다 ifnot self.isEmpty(): return self.datas[(self.front + 1) % size]
defisEmpty(self): # front가 None이면 큐가 비어있기 때문에 None을 반환한다 if self.front isNone: returnTrue else: returnFalse
defenQueue(self, data): # 데이터를 새로 삽입 # 삽입할 노드를 선언 new_node = Node(data) # 비어 있으면 front와 rear에 새로운 노드를 추가한다 if self.isEmpty(): self.front = new_node self.rear = new_node # 비어 있지않으면 기존 rear와 rear뒤에 새로운 노드를 추가한다 else: self.rear.next = new_node self.rear = new_node
defdeQueue(self): # 비어 있으면 비어있다고 출력 if self.isEmpty(): return"Queue is Empty" # 비어 있지않으면 front를 dequeued에 담고 현재 front 뒤에 있는 것을 front로 지정 else: dequeued = self.front self.front = self.front.next # front가 None이면 큐가 비었기 때문에 rear도 None으로 설정 if self.front isNone: self.rear = None return dequeued.data