본문 바로가기
Algorithm

[자료구조] 스택 Stack

Writer mintparc 2019. 12. 16.

스택이란?


데이터를 일시적으로 저장하기 위해 사용하는 자료구조이다.

데이터의 입력과 출력 순서는 가장 나중에 넣은 데이터를 가장 먼저 꺼내는 후입선출(LIFO, Last In First Out)의 방식이다. 

 

  • 스택에서 데이터를 넣는 작업 : 푸시 Push
  • 스택에서 데이터를 꺼내는 작업 : 팝 Pop
  • 푸시와 팝이 이루어지는 위치 : 꼭대기 Top
  • 스택의 가장 아랫부분 : 바닥 Bottom

 

스택의 작동


 

스택은 바닥이 막힌 원통에 공을 집어넣고 꺼내는 것과 같다. 넣는 작업을 푸시(Push) 꺼내는 작업을 팝(Pop)이라고 한다. 그림에서는 먼저 8번 공을 원통 안에 넣고, 그 다음 3번 공을 넣었다. 스택은 다시 공을 꺼낼 때 가장 마지막에 넣은 3번공부터 꺼낼 수 있는 구조이다.

 

 

 

때문에 스택에서는 가장 마지막에 들어오는 데이터를 추적할 필요가 있다. 맨 마지막에 들어오는 데이터를 꼭대기, Top, Peek 등으로 표현한다.

 

 

 

Java 내부 스택


자바에서는 메서드를 호출하고 실행할 때 프로그램 내부적으로 스택을 사용한다.

예를 들어, 이런식으로 메소드 호출을 한다면

public class Test {

	static void methodA() {
		
	}
	
	static void methodB() {
		
	}
	
	static void methodC() {
		methodA();
		methodB();
	}
	
	public static void main(String[] args) {
		methodC();
	}
}

 

이런 구조로 메서드가 호출, 실행된다.

 

 

 

스택 구현하기 1 : 기본 


class IntStack {
    int[] stk;	//스택 본체용 배열
    int max;	//스택용량
    int ptr;	//스택포인터
}

 

1-1. 스택 본체용 배열 (stk)
: 이곳에는 푸시된 데이터를 저장한다. 바닥이 막힌 원통에 해당한다.


 

1-2. 스택 용량 (max)

스택의 용량. 즉 스택에 쌓을 수 있는 최대 데이터 수를 나타낸다.

이 값은 결국 stk 배열의 길이(length)와 같다.

 

 

1-3. 스택포인터 (ptr)

스택에 쌓여있는 데이터 수를 나타낸다. 이 값은 스택포인터(Stack Pointer)라고 한다. 새로운 데이터를 삽입하거나 삭제할 인덱스를 가리키는 용도이다.

  • 비어있는 스택인 경우 : ptr = 0
  • 가득 찬 스택인 경우 ptr = max

 

1-4. 생성자 (intStack)

생성자는 스택 본체용 배열을 생성, 초기화하는 준비 작업을 수행한다. 처음 생성 시 스택은 비어있어야 하고 스택포인터는 0이어야 한다. 전달받은 값을 max에 대입해서 스택용량을 결정하고 길이가 max인 stk배열을 만든다.

 

public IntStack(int size) {
	ptr = 0;			 //스택포인트 초기화
	max = size;			 //받아온 파라미터 size로 용량(max) 초기화
	stk = new int[max];	 //길이가 max인 배열 stk
 }

 

 

스택 구현하기 2 : 푸시 메서드


데이터가 쌓일 원통을 만들었다면, 데이터를 집어넣는 메서드를 구현해야한다. 

public int push(int x) throws OverflowIntStackException {
	if (ptr >= max) {								//스택이 가득 찼을 경우 예외처리	
		throw new OverflowIntStackException();
	}
	return stk[ptr++] = x;							//푸시한 값을 반환
}

 

 

스택 구현하기 3 : 팝 메서드


스택의 꼭대기(Top, ptr)에 있는 데이터를 팝하고 그 값을 반환하는 메서드이다. 스택이 비어있어 팝할 수 없다면 예외처리한다.

public int pop() throws EmptyIntStackException {
	if (ptr <= 0){									//스택이 비어 있을 경우
		throw new EmptyIntStackException();
    }
	return stk[--ptr];							
}

 

 

스택 구현하기 4 : 피크 메서드 


스택 꼭대기에 있는 데이터를 '몰래 엿보는' 메서드이다. 스택에서 Top이 가리키는 데이터를 읽는 작업을 하며, 데이터의 입출력이 이루어지지 않으므로 스택포인터(ptr) 값의 변화는 없다.

public int peek() throws EmptyIntStackException {
	if (ptr <= 0){									//스택이 비어 있을 경우
		throw new EmptyIntStackException();
    }
	return stk[ptr - 1];							//스택 꼭대기 데이터
}

 

분류 차이점
PUSH top(ptr) 값이 증가
POP top(ptr) 값이 감소
PEEK top(ptr) 값의 변화 없음

 

 

스택 구현하기 5 : 검색메서드


스택 배열 stk에 검색할 값이 포함되어 있는지, 있다면 배열의 몇 번째 인덱스에 들어있는 지 알려주는 메서드이다. 꼭대기에서부터 바닥쪽으로 선형검색을 수행한다. 즉, stk[length-1] 부터 stk[0]까지 스캔하면서 검색할 값이 있는 지 찾아낸다. 만약 값이 있다면 찾아낸 요소의 인덱스를 반환하고 없다면 -1을 반환한다. 

단, 같은 값이 여러 개 존재한다면 꼭대기 쪽의 인덱스를 반환한다. 꼭대기 쪽에서 스캔하는 이유는 "먼저 팝이 되는 데이터"를 찾기 위해서 이기 때문이다.

public int indexOf(int x) {
	for (int i = ptr - 1; i >= 0; i--) {	//꼭대기(Top)부터 선형검색			
		if (stk[i] == x) {
			return i;						//검색성공	
		}
	}
	return -1;								//검색실패
}

 

 

스택 구현하기 6 : 스택의 모든 요소를 삭제하는 메서드


스택에 쌓여 있는 모든 데이터를 삭제하는 메서드이다. 스택포인터 값을 0으로 변경하면 된다.

public void clear() {
	ptr = 0;
}

 

 

스택 구현하기 7 : 용량 확인 메서드


생성자에서 스택 본체 배열의 용량을 max로 설정해주었다. 따라서 max를 리턴해주면 된다.

public int capacity() {
	return max;
}

 

 

스택 구현하기 8 : 데이터 수를 확인하는 메서드 


스택에 쌓여있는 데이터 수는 ptr과 같으므로 ptr을 리턴해주면 된다.

public int size() {
	return ptr;
}

 

 

스택 구현하기 9 : 스택이 비어있는 지 확인하는 메서드


public boolean isEmpty() {
	return ptr <= 0;
}

 

 

스택 구현하기 10 : 스택이 가득 차있는지 확인하는 메서드


public boolean isFull() {
	return ptr >= max;
}

댓글