스택은 데이터를 임시 저장할 때 사용하는 자료구조로 데이터의 입력과 출력 순서는 후입선출(last-in-first-out)로 처리된다. 파이썬은 스택 자료형을 따로 지원하지 않지만 리스트가 사실상 스택의 모든 연산을 지원한다.


1. 스택

스택에 데이터를 넣는 작업을 push라고 하고, 스택에서 데이터를 꺼내는 작업을 pop이라고 한다. 데이터를 넣고 꺼내는 작업을 맨 위부터 수행하며 이 윗부분을 top이라고 하고, 아래부분을 bottom이라고 한다.

image


2. 스택의 시간 복잡도

Insertion/Deletion : O(1)

스택의 원소 삽입/삭제는 맨 위의 원소에 대해서만 이루어지므로 O(1)이다. 즉, 자료의 개수가 몇 개인지와 같은 다른 어떤 사항도 고려할 필요 없이 그냥 새로운 자료를 기존의 자료 맨 위에 올리기만 하면 된다. 자료를 삭제할 때도 마찬가지로 자료의 개수가 몇 개이던지 그냥 맨 위에 있는 자료를 pop하면 되므로 자료의 삭제 또한 O(1)으로 표기할 수 있다.

Search: 최소 O(1), 최대 O(N)

검색을 시작하면 맨 위 부터 맨 아래까지 순차적으로 검색하여 자료를 찾는다. 운이 좋게 가장 위의 데이터가 우리가 찾는 것이면 단 한 번의 검색으로 답을 찾을 수 있겠지만 O(1), 만약 맨 아래 데이터가 우리가 찾는 것이라면 맨 마지막까지 검색 과정을 거쳐야할 것이다. 그러므로 스택의 검색 횟수는 가장 최악의 경우인 O(n)으로 표기할 수 있다.


3. 스택의 활용

스택은 재귀 알고리즘에서 유용하게 사용되고, DFS에 사용된다.


4. Stack with Python

스택의 기본연산은 다음과 같다.

  • push(): 스택에 원소를 추가
  • pop(): 스택 가장 위에 있는 원소를 삭제하고 그 원소를 반환
  • peek(): 스택 가장 위에 있는 원소를 반환 (삭제하지는 않음)
  • empty(): 스택이 비어있다면 1, 아니면 0을 반환

push는 list.append(x), pop은 list.pop()을 사용하면 된다. pop()은 다음과 같이 활용할 수 있다.

pop()

pop()은 리스트의 맨 마지막 요소를 돌려주고 그 요소는 삭제한다.

a = [1,2,3]
a.pop()
# 3

a
# [1, 2]

pop(x)

pop(x)는 리스트의 x번째 요소를 돌려주고 그 요소는 삭제한다.

a = [1,2,3]
a.pop(1)
# 2

a
# [1, 3]

이를 활용해 스택의 기본연산을 구현하면 다음과 같다.

class Stack:

    def __init__(self):
        self.data = []

    def size(self):
        return len(self.data)

    def push(self, item):
        self.data.append(item)

    def pop(self):
        return self.data.pop()

    def peek(self):
        return self.data[-1]
    
    def isEmpty(self):
        return self.size() == 0

위처럼 직접 클래스를 구현해도 되고, 필요할 때 알맞는 함수를 가져다가 써도 된다.

stack = []
stack.append(5)
stack.append(2)
stack.append(3)
stack.pop() # 가장 오른쪽에서 하나를 꺼내기
stack.append(7)
stack.pop()

print(stack[::-1])  #최상단의 원소부터 출력
print(stack)  # 최하단의 원소부터 출력

# [2,5]
# [5,2]

아래는 정수를 저장하는 스택을 구현하고 입력으로 주어지는 명령을 처리하는 프로그램을 작성한 것이다.

import sys

n = int(input())
stack = []

for _ in range(n):
    cmd = sys.stdin.readline().split()
    
    if cmd[0] == 'push':
        stack.append(cmd[1])
    elif cmd[0] == 'pop':
        if len(stack) == 0:
            print(-1)
        else:
            print(stack.pop())
    elif cmd[0] == 'size':
        print(len(stack))
    elif cmd[0] == 'empty':
        if not stack:
            print(1)
        else:
            print(0)
    elif cmd[0] == 'top':
        if not stack:
            print(-1)
        else:
            print(stack[-1])