1. Stack이란?
- 마지막에 들어온 데이터가 가장 먼저 나간다. 즉, 후입선출(LIFO) 방식이다.
- 맨 위의 원소에만 접근이 가능하다.
- 가상 메모리의 스택 영역에서 이와 같은 자료 구조를 이용한다.
2. Stack 구현하기
구현할 내용은 아래와 같다.
- push(E x) - 원소 x를 스택에 입력한다.
- pop() - 스택 맨 위의 원소를 삭제한다.
- top() - 스택 맨 위의 원소 값을 리턴한다.
- isEmpty() - 스택이 비었는지 여부를 리턴한다.
- popAll() - 스택의 내부 데이터를 모두 삭제한다.
- printAll() - 스택의 내부의 모든 데이터를 출력한다.
** 원래 스택에서는 맨 위의 값에만 접근이 가능하나, 테스트 편의상 printAll() 메서드를 만들어 사용하였다.
1) 인터페이스
public interface StackInterface<E> {
public void push (E x);
public void pop();
public E top();
public boolean isEmpty();
public void popAll();
public void printAll();
}
2) 클래스
- 필드 영역
//필드 영역
private E stack[];
private int topIndex;
private static final int DEFAULT_CAPACITY = 64;
- stack - 원소를 입력 받을 배열 리스트이다.
- topIndex - 스택의 맨 윗 원소의 인덱스를 저장한다.
- DEFAULT_CAPACITY - 스택 생성 시 용량을 따로 선언하지 않을 경우 설정할 기본 용량이다.
- 생성자 영역
//생성자 영역
public ArrayStack() {
stack = (E[]) new Object[DEFAULT_CAPACITY];
topIndex = -1;
}
public ArrayStack(int n) {
stack = (E[]) new Object[n];
topIndex = -1;
}
- 생성 시 입력 값으로 정수를 받으면 해당 정수 크기의 스택을, 그렇지 않으면 DEFAULT_CAPACITY 크기의 스택을 생성한다.
-메서드 영역
<push 메서드 구현>
//메서드 영역
@Override
public void push(E x) {
if (isFull()) {
System.out.println("ERROR");
} else {
topIndex++;
stack[topIndex]=x;
}
}
- 만약 stack에 남은 공간이 없는데 push를 시도하면 에러를 출력한다.
- 그렇지 않으면 topIndex를 늘려준 뒤 해당 인덱스에 입력받은 데이터를 입력한다.
<pop 메서드 구현>
@Override
public void pop() {
if (isEmpty()) {
System.out.println("ERROR");
} else {
stack[topIndex]=null;
topIndex--;
}
}
- 만약 stack이 비어 있는데 pop을 시도하면 에러를 출력한다.
- 그렇지 않다면 현재 topIndex를 null로 바꾼 후 topIndex를 1 감소시킨다.
- ** 사실 add시 해당 인덱스를 덮어 쓸 것이기 때문에 topIndex만 1 감소시키고 null 처리는 해주지 않아도 된다.
<top 메서드 구현>
@Override
public E top() {
if (isEmpty()) {
return null;
} else {
return stack[topIndex];
}
}
- 만약 스택이 비어있는데 top을 시도하면 null 값을 반환한다.
- 그렇지 않다면 stack의 topIndex값을 반환한다.
<isEmpty&isFull 메서드 구현>
@Override
public boolean isEmpty() {
return (topIndex<0);
}
//isFull메서드는 인터페이스를 오버라이딩 한 것이 아님에 주의!
public boolean isFull() {
return (topIndex==stack.length-1);
}
- isEmpty - topIndex가 음수이면 true, 아니면 false.
- isFull - topIndex와 스택의 크기를 비교하여 스택이 다 찼는지를 판별.
<popAll 메서드 구현>
@Override
public void popAll() {
stack = (E[]) new Object[stack.length];
topIndex=-1;
}
- stack을 기존 길이의 빈 배열 리스트로 덮어쓴다.
- topIndex를 초기화한다.
<printAll 메서드 구현>
@Override
public void printAll() {
for (int i=0; i<=topIndex; i++) {
System.out.print(stack[i]+" ");
}
}
- for문이 전체 스택의 인덱스를 순회하며 해당 인덱스의 값들을 프린트한다.
- 전체 코드
public class ArrayStack<E> implements StackInterface<E> {
//필드 영역
private E stack[];
private int topIndex;
private static final int DEFAULT_CAPACITY = 64;
//생성자 영역
public ArrayStack() {
stack = (E[]) new Object[DEFAULT_CAPACITY];
topIndex = -1;
}
public ArrayStack(int n) {
stack = (E[]) new Object[n];
topIndex = -1;
}
//메서드 영역
@Override
public void push(E x) {
if (isFull()) {
System.out.println("ERROR");
} else {
topIndex++;
stack[topIndex]=x;
}
}
@Override
public void pop() {
if (isEmpty()) {
System.out.println("ERROR");
} else {
stack[topIndex]=null; //안해도 됨.
topIndex--;
}
}
@Override
public E top() {
if (isEmpty()) {
return null;
} else {
return stack[topIndex];
}
}
@Override
public boolean isEmpty() {
return (topIndex<0);
}
public boolean isFull() {
return (topIndex==stack.length-1);
}
@Override
public void popAll() {
stack = (E[]) new Object[stack.length];
topIndex=-1;
}
@Override
public void printAll() {
for (int i=0; i<=topIndex; i++) {
System.out.print(stack[i]+" ");
}
}
}
3) 결과 확인하기
<코드>
public class Test {
public static void main(String[] args) {
ArrayStack<Integer> stack = new ArrayStack<>();
stack.push(100);
stack.push(200);
stack.push(300);
stack.push(400);
System.out.println(stack.top());
stack.printAll();
System.out.println();
for (int i=0; i<5; i++) {
stack.pop();
}
stack.printAll();
//스택에서 pop을 5번 수행한 뒤 출력합니다. - 원소가 4개인데 5번 pop하였으므로 에러가 발생하고, 스택이 비어있으므로 내용물은 출력되지 않음.
System.out.println(stack.isEmpty());
// 스택이 비었는지 여부를 출력합니다.
stack.push(100);
stack.printAll();
System.out.println();
//stack에 100을 입력하고 출력합니다.
stack.popAll();
stack.printAll();
//stack에 - stack을 popAll 했으므로 내용물이 출력되지 않음.
}
}
<결과>
정상적으로 출력된다.
'자료구조' 카테고리의 다른 글
[Java] 큐(Queue) 배열로 구현하기 (0) | 2022.08.01 |
---|---|
[Java] 스택(Stack) 연결 리스트로 구현하기 (0) | 2022.07.30 |
[Java] 원형 양방향 연결 리스트 (CircularDoublyLinkedList) 구현하기 (0) | 2022.07.29 |
[Java] 원형 연결 리스트(CircularLinkedList) 구현하기 (0) | 2022.07.28 |
[Java] 단일 연결 리스트(LinkedList) 구현하기 (0) | 2022.07.27 |