IntQueue 클래스
2025. 4. 20. 18:05ㆍ카테고리 없음
코드 설명
/******************************************************************************
* IntQueue 클래스는 정수를 저장하는 순서 큐(Queue)를 배열을 이용하여 구현한 클래스입니다.
******************************************************************************/
public class IntQueue implements Cloneable {
// IntQueue 클래스의 불변 조건 (Invariant):
// 1. 큐에 있는 항목의 개수는 manyItems에 저장됩니다.
// 2. 비어 있지 않은 큐의 경우, 항목들은 data[front]부터 data[rear]까지 순환 배열 형태로 저장됩니다.
// 3. 큐가 비어있는 경우, manyItems는 0이며, data는 배열을 참조하지만 front와 rear는 중요하지 않습니다.
private int[] data;
private int manyItems;
private int front;
private int rear;
/**
* 초기 용량이 10인 빈 큐를 생성합니다.
* @param - 없음
* <dt><b>후조건:</b><dd>
* 이 큐는 비어 있으며, 초기 용량은 10입니다.
* @exception OutOfMemoryError
* 메모리가 부족할 경우 발생:
* <CODE>new int[10]</CODE>.
**/
public IntQueue() {
final int INITIAL_CAPACITY = 10;
manyItems = 0;
data = new int[INITIAL_CAPACITY];
// 빈 큐에서는 front와 rear는 중요하지 않습니다.
}
/**
* 지정한 초기 용량을 가진 빈 큐를 생성합니다.
* @param initialCapacity
* 큐의 초기 용량
* <dt><b>전제조건:</b><dd>
* initialCapacity는 음수가 아니어야 합니다.
* <dt><b>후조건:</b><dd>
* 이 큐는 비어 있으며, 주어진 초기 용량을 가집니다.
* @exception IllegalArgumentException
* initialCapacity가 음수인 경우 발생.
* @exception OutOfMemoryError
* 메모리가 부족한 경우 발생:
* <CODE>new int[initialCapacity]</CODE>.
**/
public IntQueue(int initialCapacity) {
if (initialCapacity < 0)
throw new IllegalArgumentException("초기 용량이 음수입니다: " + initialCapacity);
manyItems = 0;
data = new int[initialCapacity];
}
/**
* 이 큐의 복사본을 생성합니다.
* @param - 없음
* @return
* 복사된 큐 객체. 원본과 복사본은 이후의 변경이 서로 영향을 주지 않습니다.
* @exception OutOfMemoryError
* 복사를 위한 메모리가 부족한 경우 발생.
**/
public Object clone() {
IntQueue answer;
try {
answer = (IntQueue) super.clone();
} catch (CloneNotSupportedException e) {
// 이 예외는 발생하지 않아야 하지만, 발생할 경우 clone이 불가능한 설계 오류일 수 있습니다.
throw new RuntimeException("이 클래스는 Cloneable을 구현하지 않았습니다.");
}
answer.data = (int[]) data.clone();
return answer;
}
/**
* 큐의 용량을 변경하여 최소한 minimumCapacity를 보장합니다.
* @param minimumCapacity
* 큐의 새로운 최소 용량
* <dt><b>후조건:</b><dd>
* 큐의 용량이 minimumCapacity 이상으로 설정됩니다.
* @exception OutOfMemoryError
* 메모리가 부족하여 용량 증가가 불가능한 경우 발생.
**/
public void ensureCapacity(int minimumCapacity) {
int[] biggerArray;
int n1, n2;
if (data.length >= minimumCapacity)
return;
else if (manyItems == 0)
data = new int[minimumCapacity];
else if (front <= rear) {
biggerArray = new int[minimumCapacity];
System.arraycopy(data, front, biggerArray, front, manyItems);
data = biggerArray;
} else {
biggerArray = new int[minimumCapacity];
n1 = data.length - front;
n2 = rear + 1;
System.arraycopy(data, front, biggerArray, 0, n1);
System.arraycopy(data, 0, biggerArray, n1, n2);
front = 0;
rear = manyItems - 1;
data = biggerArray;
}
}
/**
* 현재 큐의 용량을 반환합니다.
* @return
* 큐의 현재 용량
**/
public int getCapacity() {
return data.length;
}
/**
* 큐의 앞쪽 항목을 제거하고 반환합니다.
* @return
* 큐의 앞쪽 항목 값
* @exception NoSuchElementException
* 큐가 비어 있을 경우 발생.
**/
public int getFront() {
int answer;
if (manyItems == 0)
throw new NoSuchElementException("큐 언더플로우");
answer = data[front];
front = nextIndex(front);
manyItems--;
return answer;
}
/**
* 새로운 항목을 큐에 추가합니다.
* 필요 시 자동으로 용량이 늘어납니다.
* @param item
* 큐에 추가할 항목
* <dt><b>후조건:</b><dd>
* 항목이 큐에 추가됩니다.
* @exception OutOfMemoryError
* 용량을 늘릴 메모리가 부족할 경우 발생.
**/
public void insert(int item) {
if (manyItems == data.length) {
ensureCapacity(manyItems * 2 + 1);
}
if (manyItems == 0) {
front = 0;
rear = 0;
} else
rear = nextIndex(rear);
data[rear] = item;
manyItems++;
}
/**
* 큐가 비어 있는지 확인합니다.
* @return
* 큐가 비어 있으면 true, 그렇지 않으면 false
**/
public boolean isEmpty() {
return (manyItems == 0);
}
private int nextIndex(int i) {
// 전제조건: 0 <= i < data.length
// 후조건: i+1이 data.length이면 0을 반환, 아니면 i+1을 반환
if (++i == data.length)
return 0;
else
return i;
}
/**
* 큐에 들어 있는 항목 수를 반환합니다.
* @return
* 큐에 저장된 항목 수
**/
public int size() {
return manyItems;
}
/**
* 큐의 용량을 실제 항목 수만큼 줄입니다.
* @exception OutOfMemoryError
* 메모리 부족으로 인해 용량 조정이 불가능한 경우 발생.
**/
public void trimToSize() {
int[] trimmedArray;
int n1, n2;
if (data.length == manyItems)
return;
else if (manyItems == 0)
data = new int[0];
else if (front <= rear) {
trimmedArray = new int[manyItems];
System.arraycopy(data, front, trimmedArray, front, manyItems);
data = trimmedArray;
} else {
trimmedArray = new int[manyItems];
n1 = data.length - front;
n2 = rear + 1;
System.arraycopy(data, front, trimmedArray, 0, n1);
System.arraycopy(data, 0, trimmedArray, n1, n2);
front = 0;
rear = manyItems - 1;
data = trimmedArray;
}
}
}
인스턴스 멤버
private int[] data;
private int manyItems;
private int front;
private int rear;
- data에는 데이터를 저장해 준다.
- manyItems에는 데이터의 개수를 저장해 준다.
- front부터 rear까지 순환 배열의 구조로 데이터를 저장해 둔다.
생성자
public IntQueue() {
final int INITIAL_CAPACITY = 10;
manyItems = 0;
data = new int[INITIAL_CAPACITY];
}
- 기본적으로 배열의 크기를 10으로 지정해 둔다.
public IntQueue(int initialCapacity) {
if (initialCapacity < 0)
throw new IllegalArgumentException("초기 용량이 음수입니다: " + initialCapacity);
manyItems = 0;
data = new int[initialCapacity];
}
- initialCapacity를 기본적으로 배열의 크기를 지정해 둔다.
- 0보다 작은 경우에만 예외를 발생시켜 준다.
메서드
public Object clone() {
IntQueue answer;
try {
answer = (IntQueue) super.clone();
} catch (CloneNotSupportedException e) {
// 이 예외는 발생하지 않아야 하지만, 발생할 경우 clone이 불가능한 설계 오류일 수 있습니다.
throw new RuntimeException("이 클래스는 Cloneable을 구현하지 않았습니다.");
}
answer.data = (int[]) data.clone();
return answer;
}
- (IntQueue) super.clone()으로 얕은 복사를 해주고, (int []) data.clone()으로 answer.data에 깊은 복사를 해준다.
public void ensureCapacity(int minimumCapacity) {
int[] biggerArray;
int n1, n2;
if (data.length >= minimumCapacity)
return;
else if (manyItems == 0)
data = new int[minimumCapacity];
else if (front <= rear) {
biggerArray = new int[minimumCapacity];
System.arraycopy(data, front, biggerArray, front, manyItems);
data = biggerArray;
} else {
biggerArray = new int[minimumCapacity];
n1 = data.length - front;
n2 = rear + 1;
System.arraycopy(data, front, biggerArray, 0, n1);
System.arraycopy(data, 0, biggerArray, n1, n2);
front = 0;
rear = manyItems - 1;
data = biggerArray;
}
}
- 기본적으로 minimumCapacity보다 데이터의 용량이 더 크면 그냥 리턴해준다.
- 그리고 데이터의 개수가 0인 경우에는 data의 용량을 minimumCapacity 해주고 리턴해준다.
- 만약 front <=rear인 경우에는 front부터 manyItems만큼의 데이터를 복사해 주고 리턴해주면 된다.
- 반대로 rear <front인 경우에는 두 번을 나누어서 데이터를 복사해주어야 한다.
1)
-front~끝까지 데이터를 복사해주어야 함!
-즉, front부터 시작해서 (data.length-front) 만큼의 데이터를 biggerArray의 0~(data.length-front)까지의 위치에 저장해주어야 한다.
2)
-이번에는 처음부터 0번부터 시작하여서 (rear+1) 개만큼의 데이터를 biggerArray에 (data.length-front)부터 복사해주어야 한다.
3)
이후에는 front를 0, rear를 manyItems-1로 지정해 준다.
public int getCapacity() {
return data.length;
}
- 배열의 용량을 리턴해준다.
private int nextIndex(int i) {
if (++i == data.length)
return 0;
else
return i;
}
- 다음에 있는 데이터의 인덱스를 가리키는 메서드이다.
- 만약 다음 인덱스가 데이터의 용량과 동일한 경우 0, 즉 맨 처음 인덱스를 리턴해줘야 한다.
public int getFront() {
int answer;
if (manyItems == 0)
throw new NoSuchElementException("큐 언더플로우");
answer = data[front];
front = nextIndex(front);
manyItems--;
return answer;
}
- 만약 데이터의 개수(manyItems)가 0인 경우에는 예외 처리를 발생시켜 준다.
- 그리고 front를 1 증가시켜서 데이터를 줄여주고, manyItems 또한 1 감소시켜 준다.
public void insert(int item) {
if (manyItems == data.length) {
ensureCapacity(manyItems * 2 + 1);
}
if (manyItems == 0) {
front = 0;
rear = 0;
} else
rear = nextIndex(rear);
data[rear] = item;
manyItems++;
}
- 데이터의 용량이 꽉 찬 경우에는 두 배 정도 용량을 늘려준다.
- 만약 데이터의 개수가 0인 경우에는 front=rear=0으로 지정해 준다.
- 아니라면 rear를 nextIndex 메서드를 활용하여서 다음 인덱스를 구해준다.
- 그러고 나서 rear에 해당하는 위치에 데이터를 저장해 주고 데이터 개수(manyItems)를 1 늘려준다.
public boolean isEmpty() {
return (manyItems == 0);
}
- 데이터 개수가 0이면 true 아니면 false를 리턴해준다.
public int size() {
return manyItems;
}
- 데이터의 개수를 리턴해준다.
public void trimToSize() {
int[] trimmedArray;
int n1, n2;
if (data.length == manyItems)
return;
else if (manyItems == 0)
data = new int[0];
else if (front <= rear) {
trimmedArray = new int[manyItems];
System.arraycopy(data, front, trimmedArray, front, manyItems);
data = trimmedArray;
} else {
trimmedArray = new int[manyItems];
n1 = data.length - front;
n2 = rear + 1;
System.arraycopy(data, front, trimmedArray, 0, n1);
System.arraycopy(data, 0, trimmedArray, n1, n2);
front = 0;
rear = manyItems - 1;
data = trimmedArray;
}
}
- 만약 data의 용량이 데이터의 개수와 동일하다면 그냥 리턴해준다.
- 그리고 데이터의 개수가 0이면 data의 용량을 0으로 지정해 주고 리턴한다.
- 만약 front <=rear인 경우에는 front부터 rear까지를 복사해 준다.
- 반대로 rear <front이면 위에서 ensureCapacity 해준 것과 비슷하게 저장해 준다.