# 큐 (Queue)
정의
큐는 먼저 집어넣은 데이터가 먼저 나오는 성질(FIFO, First In First Out)을 지닌 자료구조입니다.
- 먼저 집어넣은 데이터가 먼저 나오는 스택과는 반대의 개념입니다.
- 한쪽 끝, 프런트(front)에서는 삽입만 이루어지며, 다른 한쪽 끝끝은 리어(rear)에서는 삭제만 이루어집니다.
- CPU 작업을 기다리는 프로세스, 스레드 또는 네트워크 접속을 기다리는 행렬, 너비우선 탬색(BFS), 캐시 등에 사용됩니다.
# 큐의 종류
자바에서 제공하는 큐는 인터페이스이고, 큐를 구현하는 클래스는 크게 3가지가 있습니다.
- PriorityQueue(우선순위 큐)
- 높은 우선순위의 요소를 먼저 꺼내서 처리하는 구조입니다.
- 내부구조가 힙으로 구성되어 있습니다.
- ArrayDeque(배열 양방향 큐)
- 큐의 양쪽에서 데이터의 삽입과 삭제가 모두 가능한 구조입니다.
- Queue를 상속받은 Dequeue 인터페이스를 사용해야 합니다.
- Stack이나 Queue보다 빠르지만, Thread-Safe하지 않다는 단점이 있습니다.
- LinkedList(연결리스트)
- 대중적이고 쉬운 큐의 사용방식입니다.
- 배열로 큐를 만든다면, 요소의 양에 따라 배열의 크기를 조절하거나, 원형 큐(Circular Queue)의 형태로 만들어야 하는데, linkedlist를 사용한다면 그러한 단점들이 사라집니다.
큐의 발전
일반 큐의 단점 : 큐에 빈 메모리가 남아 있어도, 꽉 차있는것으로 판단할 수도 있습니다. (rear
가 끝에 도달했을 때)
원형 큐 : 논리적으로 배열의 처음과 끝이 연결되어 있는 것으로 간주합니다.
원형 큐의 단점 : 메모리 공간은 잘 활용하지만, 배열로 구현되어 있기 때문에 큐의 크기가 제한됩니다.
연결리스트 큐 : 크기 제한이 없고 삽입, 삭제가 편리합니다.
# 데이터 삽입&삭제 속도
O(1)
- 입구 데이터를 바로 삽입하고, 출구에서 바로 삭제(꺼내기)하면 됩니다.
# 데이터 탐색 속도
O(n)
- 찾는 데이터가 존재하는지 투입된 순서대로 순차 검색이 필요합니다.
- 따라서 운이 안 좋으면 저장된 모든 값을 확인해야 할 수 도 있습니다.
# 자바에서의 큐
Collection
인터페이스를 상속 받는 인터페이스 입니다.
import java.util.Queue;
import java.util.LinkedList;
public class Sample() {
public static void main(String[] args) {
// 큐 만들기
Queue<Integer> queue = new LinkedList<>(); // linkedlist 이용
// 큐의 마지막에 요소를 추가
queue.offer(10);
queue.add(20);
// 큐의 첫번째 요소를 제거하지 않고 반환
Integer a = queue.peek();
Integer b = queue.element();
System.out.println(a); //10
System.out.println(b); //20
// 큐의 첫번째 요소를 제거하고 제거된 요소를 반환
Integer c = q.poll();
Integer d = q.remove();
System.out.println(c); //10
System.out.println(d); //20
}
}
- 위의 항목은 오로지
Queue
인터페이스에서만 추가된 메소드입니다. offer()
와add()
는 동일한 역할을 수행하는 것처럼 보이지만, 차이점은add()
는 공간이 부족해서 삽입이 불가할 때IllegalStateException
이 발생합니다.peek()
와element()
는 동일한 역할을 수행하는 것처럼 보이지만, 차이점은element()
는 비어있는 상태 일 때NoSuchElementException
이 발생합니다.poll()
와remove()
는 동일한 역할을 수행하는 것처럼 보이지만, 차이점은remove()
는 비어있는 상태 일 때NoSuchElementException
이 발생합니다.offer()
,peek()
,poll()
은 예외를 던지는 것이 아니라, 특별한 값 (null
또는false
)를 던진다는 것입니다.
예를 들어, 큐가 비어있는데 remove()를 하면 NoSuchElementException 예외가 발생하지만, poll()을 하면 null값이 반환됩니다.
- 다른 메소드는
Collections
인터페이스 의 메소드를 이용합니다. - 결국 둘다 인터페이스이기에 구현체인
LinkedList
에서 호출되는 것이지만....
# 2개의 스택으로 큐를 구현하기
- inbox에 데이터를 삽입한다(push) -> A,B
- inbox에 있는 데이터를 추출(pop)하여 outbox에 삽입(push) 한다. -> B,A
- outbox에 있는 데이터를 추출(pop)한다. -> A,B 순으로 출력된다.
import java.util.Stack;
public class Queue {
private Stack inBox = new Stack();
private Stack outBox = new Stack();
public void enQueue(Object item) {
inBox.add(item);
}
public Object deQueue() {
if (outBox.isEmpty()) {
while(!inBox.isEmpty()) {
outBox.push(inBox.pop());
}
}
return outBox.pop();
}
public static void main(String[] args) {
Queue queue = new Queue();
queue.enQueue("A");
queue.enQueue("B");
queue.enQueue("C");
System.out.println(queue.deQueue());
System.out.println(queue.deQueue());
System.out.println(queue.deQueue());
}
}
# 참고자료
- 주홍철.면접을 위한 CS 전공지식 노트.서울:길벗,2022.
- https://galid1.tistory.com/483
- https://st-lab.tistory.com/181
- Oracle Doc (opens new window)
- HyeminNoh (opens new window)
- gyoogle (opens new window)
- DevAndy (opens new window)
- Creator Developer:티스토리 (opens new window)
← 스택 (Stack) 덱 (Deque) →