Java의 Stack 이해하기:
Java의 Stack 클래스는 ‘후입선출(LIFO: Last-In, First-Out)’ 원칙을 따르는 자료구조이다. 접시를 쌓거나 책을 쌓는 것과 비슷하게, 가장 나중에 들어간 요소가 가장 먼저 나오는 구조이다.
1. Stack의 시각적 이해
Stack은 마치 한쪽 끝이 막힌 통과 같다고 생각할 수 있다.
•
요소 추가 (Push): 통의 위쪽(맨 위)으로 새로운 요소를 추가한다.
•
요소 제거 (Pop): 통의 위쪽(맨 위)에서 가장 최근에 추가된 요소를 제거한다.
•
요소 확인 (Peek): 통의 위쪽(맨 위)에 있는 요소를 확인하지만 제거하지는 않는다.
•
비어있는지 확인 (Empty): 통이 비어있는지 확인한다.
•
요소 위치 확인 (Search): 특정 요소가 통 안의 어느 위치에 있는지 확인한다.
시각적 예시:
아래 그림은 Stack의 기본적인 동작을 시각적으로 보여준다.
초기 상태:
+-----+
| |
+-----+
| |
+-----+
| |
+-----+
| |
+-----+
| |
+-----+
(바닥)
Plain Text
복사
1.
push(”A”) 실행 후:
+-----+
| A | <-- Top (가장 최근에 추가된 요소)
+-----+
| |
+-----+
| |
+-----+
| |
+-----+
| |
+-----+
| |
+-----+
(바닥)
Plain Text
복사
2.
push(”B”) 실행 후:
+-----+
| B | <-- Top
+-----+
| A |
+-----+
| |
+-----+
| |
+-----+
| |
+-----+
| |
+-----+
(바닥)
Plain Text
복사
3.
push(”C”) 실행 후:
+-----+
| C | <-- Top
+-----+
| B |
+-----+
| A |
+-----+
| |
+-----+
| |
+-----+
| |
+-----+
(바닥)
Plain Text
복사
4.
pop() 실행 후 (가장 최근에 추가된 “C”가 제거됨):
+-----+
| B | <-- Top (이제 "B"가 맨 위)
+-----+
| A |
+-----+
| |
+-----+
| |
+-----+
| |
+-----+
| |
+-----+
(바닥)
Plain Text
복사
5.
peek() 실행 시 (”B”를 확인하지만 제거하지 않음)
+-----+
| B | <-- Top
+-----+
| A |
+-----+
| |
+-----+
| |
+-----+
| |
+-----+
| |
+-----+
(바닥)
Plain Text
복사
2. Java
메서드 | 설명 | 반환 타입 |
push(E item) | 스택의 맨 위에 요소를 추가한다. | E (추가된 요소) |
pop() | 스택의 맨 위 요소를 제거하고 해당 요소를 반환한다. (스택이 비어있으면 EmptyStackException 발생) | E (제거된 요소) |
peek() | 스택의 맨 위 요소를 반환하지만 제거하지는 않는다.
(스택이 비어있으면 EmptyStackException 발생) | E (맨 위 요소) |
empty() | 스택이 비어있는지 여부를 확인한다. | boolean |
search(Object o) | 스택에서 특정 요소의 1부터 시작하는 위치를 반환한다. 찾지 못하면 -1을 반환한다. | int |
3. Java Stack 클래스 사용 예제 코드
다음은 Stack 클래스의 주요 메서드를 사용하여 문자열 요소를 조작하는 예제 코드이다.
import java.util.Stack;
import java.util.EmptyStackException; // EmptyStackException을 명시적으로 import
public class StackExample {
public static void main(String[] args) {
// 1. Stack 생성
Stack<String> myStack = new Stack<>();
System.out.println("초기 스택 상태: " + myStack); // []
System.out.println("스택이 비어있나요? " + myStack.empty()); // true
System.out.println("-------------------------------------");
// 2. push() 메서드를 사용하여 요소 추가
System.out.println("요소 'Apple' 푸시...");
myStack.push("Apple");
System.out.println("현재 스택: " + myStack); // [Apple]
System.out.println("요소 'Banana' 푸시...");
myStack.push("Banana");
System.out.println("현재 스택: " + myStack); // [Apple, Banana]
System.out.println("요소 'Cherry' 푸시...");
myStack.push("Cherry");
System.out.println("현재 스택: " + myStack); // [Apple, Banana, Cherry]
System.out.println("스택이 비어있나요? " + myStack.empty()); // false
System.out.println("-------------------------------------");
// 3. peek() 메서드를 사용하여 맨 위 요소 확인
try {
String topElement = myStack.peek();
System.out.println("맨 위 요소 (peek): " + topElement); // Cherry
System.out.println("peek 후 스택 상태: " + myStack); // [Apple, Banana, Cherry] (변화 없음)
} catch (EmptyStackException e) {
System.out.println("스택이 비어있어서 peek 할 수 없습니다.");
}
System.out.println("-------------------------------------");
// 4. pop() 메서드를 사용하여 요소 제거
try {
String poppedElement1 = myStack.pop();
System.out.println("팝된 요소: " + poppedElement1); // Cherry
System.out.println("pop 후 스택 상태: " + myStack); // [Apple, Banana]
String poppedElement2 = myStack.pop();
System.out.println("팝된 요소: " + poppedElement2); // Banana
System.out.println("pop 후 스택 상태: " + myStack); // [Apple]
} catch (EmptyStackException e) {
System.out.println("스택이 비어있어서 pop 할 수 없습니다.");
}
System.out.println("-------------------------------------");
// 5. search() 메서드를 사용하여 요소 검색
System.out.println("'Apple'의 위치: " + myStack.search("Apple")); // 1 (스택의 맨 위에서부터 1부터 시작)
System.out.println("'Banana'의 위치 (현재 스택에 없음): " + myStack.search("Banana")); // -1
System.out.println("-------------------------------------");
// 6. 스택의 모든 요소 비우기
System.out.println("스택의 모든 요소 팝:");
while (!myStack.empty()) {
System.out.println("팝된 요소: " + myStack.pop());
}
System.out.println("최종 스택 상태: " + myStack); // []
System.out.println("스택이 비어있나요? " + myStack.empty()); // true
System.out.println("-------------------------------------");
// 7. 빈 스택에서 pop/peek 시도 (EmptyStackException 발생 예시)
try {
myStack.pop();
} catch (EmptyStackException e) {
System.out.println("오류: 빈 스택에서 pop 시도! (EmptyStackException 발생)");
}
}
}
Java
복사
4. Stack의 사용 사례 (예시)
•
웹 브라우저의 뒤로 가기/앞으로 가기 기능: 방문한 페이지 URL을 스택에 저장하여 뒤로 가기 시 이전 페이지로 이동.
•
메서드 호출 스택 (Call Stack): 프로그램에서 메서드가 호출될 때마다 스택에 쌓이고, 메서드가 종료될 때 스택에서 제거된다.
•
괄호 매칭: 수식에서 괄호의 짝이 맞는지 검사할 때 (여는 괄호는 push, 닫는 괄호는 pop하여 짝 검사).
•
수식 계산 (후위 표기법): 후위 표기법으로 된 수식을 계산할 때 피연산자는 push, 연산자는 pop하여 계산.