FIFO(First In First Out) 순서를 보장하는 큐 (Queue) 는 소프트웨어 시스템에서 빈번하게 사용되는 추상 자료형입니다. 동적으로 크기가 조절되는 링크드 리스트 대신, 고정된 용량의 정적 배열을 활용하면 메모리 오버헤드를 줄이고 접근 속도를 향상시킬 수 있습니다. 본 문서에서는 Java 환경에서 배열 기반의 큐를 구축하고, 네 가지 핵심 연산을 수행하는 로직을 상세히 설명합니다.
지원해야 하는 연산 정의
- 삽입 (Push): 주어진 정수 값을 큐의 맨 뒤에 추가합니다.
- 제거 (Pop): 현재 큐의 맨 앞에 위치한 원소를 제거합니다.
- 공백 확인 (Empty): 큐 내부에 데이터가 남아있는지 여부를 판별합니다.
- 선두 조회 (Query): 큐의 가장 앞쪽 원소의 값을 반환합니다.
입출력 스펙 및 제약 조건
총 M 번의 작업이 차례로 입력됩니다. 각 작업 명령은 위 네 가지 중 하나로 주어집니다. 특히 공백 확인과 선두 조회 명령이 실행될 때마다 해당 결과를 즉시 출력해야 합니다. 데이터 범위는 작업 횟수 M 이 최대 10 만 건이며, 처리할 수 값 x 는 10 억 이하의 정수입니다. 잘못된 호출 상황 (비어 있을 때 삭제 시도 등) 은 발생하지 않는다고 가정합니다.
입력 예시:
10
push 6
empty
query
pop
empty
push 3
push 4
pop
query
push 6
출력 예시:
NO
6
YES
4
구현 알고리즘 설명
배열로 큐를 구현할 때는 두 개의 포인터 변수를 유지 관리해야 합니다. head 는 제거될 다음 요소의 인덱스를, tail 는 삽입될 위치의 인덱스를 가리킵니다. 초기에는 둘 다 0 입니다. 삽입 시 데이터를 tail 위치에 저장하고 포인터를 증가시키며, 제거 시 head 포인터만 증가시켜 논리적으로 요소를 지운 상태로 처리합니다. 큐가 비어 있는지는 두 포인터가 일치하는지를 비교하여 판단합니다. 최대 삽입 횟수는 M 번이므로, 배열 크기를 M 보다 크게 확보하면 인덱스 범위를 벗어나는 오류를 방지할 수 있습니다.
코드 작성 사례
대용량 입출력을 고려하여 BufferedReader 와 BufferedWriter 를 적용했습니다. 또한 문자열 분해를 위해 StringTokenizer 를 사용하여 성능을 최적화하였습니다.
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.IOException;
import java.util.StringTokenizer;
public class StaticQueueSolver {
public static void main(String[] args) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(System.out));
String line = reader.readLine();
if (line == null) return;
int totalOps = Integer.parseInt(line);
// 최대 작업 횟수만큼 수용 가능한 정적 배열 생성
int[] dataStore = new int[totalOps + 1];
int frontPtr = 0; // 추출 위치를 가리키는 포인터
int rearPtr = 0; // 삽입 위치를 가리키는 포인터
for (int i = 0; i < totalOps; i++) {
StringTokenizer st = new StringTokenizer(reader.readLine());
String command = st.nextToken();
if (command.equals("push")) {
int value = Integer.parseInt(st.nextToken());
dataStore[rearPtr] = value;
rearPtr++;
} else if (command.equals("pop")) {
frontPtr++;
} else if (command.equals("empty")) {
writer.write((frontPtr == rearPtr) ? "YES\n" : "NO\n");
} else if (command.equals("query")) {
writer.write(Integer.toString(dataStore[frontPtr]));
writer.write("\n");
}
}
writer.flush();
writer.close();
reader.close();
}
}