큐 (Queue)
큐 (Queue)
- 먼저 들어간 데이터가 먼저 나오는 구조 (선입선출)
(FIFO, First-In, First-Out) - 마트에서 계산 대기할 때, 영화관 입장 시 등등
- 데이터 삽입 시 위치를 알기 위한 Rear 변수 필요
데이터 반환 시 위치를 알기 위한 Front 변수 필요 - 데이터 삽입과 반환이 이루어지는 위치가 다름
(스택은 동일한 위치에서 pop과 push가 이루어지지만, 큐는 Rear, Front를 통해 위치를 알아내야 함)
추상자료형 (ADT)
자료형 | 반환값 | 설명 |
initialize() | void | 큐(Queue) 초기화 |
isEmpty() | boolean | 큐가 비어있는지 확인 |
enqueue(Data) | void | 큐에 데이터 삽입 |
dequeue() | Data | 맨 앞에 있는 데이터 반환 및 삭제 |
peek() | Data | 맨 앞에 있는 데이터 반환 후 삭제하지 않음 |
배열기반 큐 구현
- 삽입
- 삭제
- 삭제 과정의 문제점
- 아래와 같이 Rear가 배열의 끝까지 이동했지만, 삭제된 공간에는 데이터가 저장되지 않음
- dequeue 시 삭제된 빈 공간을 뒤에 데이터들이 채워줘야하는데, 잦은 데이터의 이동이 발생할 경우 성능에 문제가 생길 수 있어 이를 해결하기 위해 front와 rear의 위치만 변경하도록 해야함 - 해결방법
- rear와 front가 가리키는 인덱스가 배열의 크기보다 클 경우 front또는 rear값을 0으로 설정하여 배열의 첫번째를 가리킬 수 있도록 함 (원형 큐)
- 구현
Queue 인터페이스 구현
package Queue; public interface Queue { // 큐(Queue) 초기화 void initialize(); // 비어있는지 확인 boolean isEmpty(); // 큐에 데이터 삽입 void enqueue(Object data); // 큐의 맨 앞에있는 데이터 반환 후 삭제 Object dequeue(); // 큐의 맨 앞에있는 데이터 반환 후 삭제하지 않음 Object peek(); }
Queue 구현
package Queue.Array; import Queue.Queue; public class ArrayQueue implements Queue { private final static int QUEUE_SIZE = 5; int frontIndex = 0; int rearIndex = 0; int countOfData = 0; Object[] queue = null; @Override public void initialize() { queue = new Object[QUEUE_SIZE]; frontIndex = 0; rearIndex = 0; countOfData = 0; } @Override public boolean isEmpty() { if (countOfData == 0){ return true; } return false; } @Override public void enqueue(Object data) { if (countOfData == QUEUE_SIZE){ System.out.println("더이상 데이터를 추가할 수 없습니다."); return; } // 배열의 끝까지 간 경우 배열의 맨 앞을 가리키도록 rear를 0으로 초기화 if (rearIndex == QUEUE_SIZE){ rearIndex = 0; } countOfData++; queue[rearIndex++] = data; } @Override public Object dequeue() { if (countOfData == 0){ System.out.println("데이터가 없습니다."); return null; } // 배열의 끝까지 간 경우 배열의 맨 앞을 가리키도록 front를 0으로 초기화 if (frontIndex == QUEUE_SIZE){ frontIndex = 0; } countOfData--; return queue[frontIndex++]; } @Override public Object peek() { if (countOfData == 0){ System.out.println("데이터가 없습니다."); return null; } return queue[frontIndex]; } }
테스트 구현
package Queue.Array; import Queue.Queue; public class ArrayQueueMain { public static void main(String[] args) { Queue queue = new ArrayQueue(); queue.initialize(); queue.enqueue(1);queue.enqueue(2); queue.enqueue(3);queue.enqueue(4); queue.enqueue(5); // 데이터 삽입 후 출력 System.out.println("데이터 삽입 후 출력"); while(!queue.isEmpty()){ System.out.println(queue.dequeue()); } System.out.println("데이터 삭제 후 하나 추가 출력 "); queue.enqueue(1);queue.enqueue(2); queue.enqueue(3);queue.enqueue(4); queue.enqueue(5); queue.dequeue(); queue.enqueue(6); while(!queue.isEmpty()){ System.out.println(queue.dequeue()); } } }
연결 리스트 기반 큐 구현
- 배열 기반의 큐와 동일하게 front와 rear 변수 필요
- 삽입 시 첫 번째 노드와 두 번째 이후의 노드 추가 과정이 다름
- 삽입
- 삭제
- front로 큐가 비어있는지 판별할 수 있기 때문에 삭제 시 rear는 신경쓰지 않아도 됨
구현
- 인터페이스는 동일하게 구현
- LinkedList 큐 구현
package Queue.LinkedList; import Queue.Queue; public class LinkedListQueue implements Queue { class Node { Object data; Node nextNode; } Node front = null; Node rear = null; int countOfData = 0; @Override public void initialize() { front = null; rear = null; countOfData = 0; } @Override public boolean isEmpty() { if (front == null){ return true; } return false; } @Override public void enqueue(Object data) { Node newNode = new Node(); newNode.data = data; // 큐가 비어있는 경우 첫 번째 노드 추가 if (isEmpty()){ front = newNode; rear = newNode; } // 두 번째 이후의 노드 추가일 경우 rear의 다음 node 주소를 설정 후 rear값 변경 else { rear.nextNode = newNode; rear = newNode; } countOfData++; } @Override public Object dequeue() { if (isEmpty()){ System.out.println("데이터가 없습니다."); return null; } // 제일 앞 쪽 데이터 반환 Object data = front.data; // front의 다음 노드를 front로 변경 front = front.nextNode; return data; } @Override public Object peek() { if (isEmpty()){ System.out.println("데이터가 없습니다."); return null; } return front.data; } }
- 테스트 구현
package Queue.LinkedList; import Queue.Queue; public class LinkedListQueueMain { public static void main(String[] args) { Queue queue = new LinkedListQueue(); queue.initialize(); queue.enqueue(1);queue.enqueue(2); queue.enqueue(3);queue.enqueue(4); queue.enqueue(5); // 데이터 삽입 후 출력 System.out.println("데이터 삽입 후 출력"); while(!queue.isEmpty()){ System.out.println(queue.dequeue()); } System.out.println("데이터 삭제 후 하나 추가 출력 "); queue.enqueue(1);queue.enqueue(2); queue.enqueue(3);queue.enqueue(4); queue.enqueue(5); queue.dequeue(); queue.enqueue(6); while(!queue.isEmpty()){ System.out.println(queue.dequeue()); } } }
'0x00. 자료구조' 카테고리의 다른 글
우선순위 큐(Priority Queue)와 힙 (Heap) (0) | 2021.10.27 |
---|---|
[Java] 트리 (Tree)와 이진트리 (Binary Tree) (0) | 2021.10.23 |
스택을 이용한 후위 표기법 및 계산기 (postfix) [JAVA] (0) | 2021.10.18 |
스택 (Stack) (0) | 2021.10.15 |
양방향 연결 리스트 (이중 연결 리스트) (0) | 2021.10.14 |