Stack(스택)
사전적으로 Stack(스택)은 '쌓다', '더미'라는 의미를 가지고 있다. 접시를 차곡차곡 쌓아 올리듯이 데이터를 쌓아올리는 형상을 생각하면 된다. Stack(스택)은 Queue(큐)와 함께 자바에서 사용되는 가장 기본적인 자료구조 중 하나다.
Stack(스택)은 '마지막에 추가된 데이터가 가장 먼저 나오는' 특징을 가지고 있다. LIFO(Last In First Out) 동작이라고 한다. 함께 많이 사용되는 Queue(큐)의 경우 먼저 추가된 데이터가 먼저 나오는 FIFO(First In First Out) 동작을 갖는것과 비교된다.
일반적으로 스택에 데이터를 추가하는 동작은 'push'라고 하며, 스택에서 데이터를 빼는 동작은 'pop'이라고 한다. pop 메소드를 실행하면 가장 마지막에 push 된 데이터가 튀어나오게 된다.
자바는 java.util.Stack 클래스를 통해 Stack(스택) 동작을 제공하고 있다. Queue(큐)와 더불어 Stack(스택)은 자바를 이용해 다양한 문제 해결을 하는데 많이 사용된다.
Stack(스택) 사용법
import java.util.Stack;
public class StackExample {
public static void main(String[] args) {
Stack<String> stack = new Stack<>();
// Stack에 데이터 추가
stack.push("Data1");
stack.push("Data2");
stack.push("Data3");
// Stack에서 데이터 꺼내기
System.out.println(stack.pop());
// Stack의 최상단 값 출력(제거하지 않음)
System.out.println(stack.peek());
// Stack에서 데이터 꺼내기
System.out.println(stack.pop());
}
}
앞서 말한 것처럼 자바는 java.util.Stack 클래스를 통해 스택을 구현해놨다. 자바 코드에서 스택을 사용하고 싶다면 Stack<String> stack = new Stack<>(); 같이 할당해서 사용할 수 있다.
Stack - push 동작(값 추가)
Stack 클래스는 push(value) 메소드를 이용해서 스택에 값을 추가할 수 있다.
접시를 테이블 위에 쌓는 것처럼 push() 메소드를 이용해서 데이터를 추가하면 차곡차곡 하나씩 데이터가 스택 자료구조에 쌓이게 된다.
stack.push("Data1");
stack.push("Data2");
stack.push("Data3");
이런 순서로 데이터를 스택에 추가했다면 pop() 메소드를 3번 호출 했을 때, "Data3", "Data2", "Data1" 순으로 데이터가 튀어나오게 된다.
java.util.Stack 클래스의 경우 별도의 사이즈를 명시하지 않는다. 처음 스택이 생성되었을때 10개의 데이터를 저장할 수 있는 공간이 할당된다. 이후 push 메소드를 통해 데이터가 추가되어 10개가 넘어가면 현재 스택 사이즈의 2배에 해당하는 공간을 할당하고, 기존 데이터를 복사하게 된다. (스택의 크기는 Integer.MAX_VALUE - 8개까지 늘어난다)
Stack - pop 동작 (값 제거)
Stack 클래스는 pop() 메소드를 이용해서 스택으로부터 값을 제거할 수 있다.
쌓여있는 접시 더미에서 접시를 꺼낼 때에는 맨 위에 쌓여있는 접시들부터 꺼내게 된다. 마찬가지로 pop 메소드는 가장 마지막에 추가된 데이터를 빼내게 된다.
Stack - peek 동작(최상단 값 확인)
스택의 최상단 값을 확인만하고 스택에서 제거하고 싶지 않은 경우도 있다.
이 경우 peek() 메소드를 호출하면된다. 스택의 최상단(Top)에 있는 데이터를 확인만하고 스택에서 제거하지 않는다. 따라서 peek() 메소드를 여러번 반복해서 호출했을 때, pop 메소드나 push 메소드, clear() 메소드가 실행된 적이 없다면 스택 데이터는 변화하지 않았을 것이고, 항상 같은 데이터가 리턴된다.
Stack - 기타 동작들
size() 메소드는 현재 스택에 들어있는 데이터의 개수를 리턴한다.
자바 Stack 클래스에는 clear() 메소드가 있다. 이 메소드는 스택에 있는 모든 데이터를 한번에 날려준다. (Stack에 저장되어 있는 데이터 값들을 하나하나 null 값으로 할당해준다.) 즉, size() 메소드가 0을 리턴하도록 만들어준다.
empty() 메소드는 스택이 비어있는지 여부를 판단할 때 사용한다. Stack에 남아있는 데이터가 하나라도 있으면 empty() 메소드가 false를 리턴한다. 즉, size() 메소드를 호출한 결과가 0인지 체크한다.
contains() 메소드는 Stack에 특정 데이터가 포함되어 있는지 체크하는 메소드다. 스택에 들어있는 모든 엘리먼트들을 순회하면서 equals() 메소드를 호출해 cotains() 메소드에 입력한 값이 스택에 들어있는지 체크한다.
댓글