2 minute read

스택(Stack) 이란?


스택(Stack)은 LIFO(Last In First Out), 즉 후입선출 방식을 따르는 자료구조입니다. 마치 접시를 쌓아놓은 것처럼, 가장 나중에 들어온 데이터가 가장 먼저 나가는 구조입니다.
데이터를 삽입하는 것을 push, 삭제하는 것을 pop이라고 합니다. 스택은 다음과 같은 특징을 가지고 있습니다.

  • LIFO (Last In First Out): 가장 나중에 들어온 데이터가 가장 먼저 나갑니다. 마치 창고에 물건을 쌓아놓은 것처럼, 가장 위에 있는 물건부터 꺼내야 합니다.
  • 접근 제한: 데이터는 스택의 맨 위(top)에서만 접근할 수 있습니다. 마치 탑처럼, 스택의 중간에 있는 데이터에는 직접 접근할 수 없습니다.

장단점


장점

  • 간단하고 직관적인 구조: LIFO 방식은 이해하기 쉽고 구현하기 간편합니다. 마치 쌓아놓은 블록처럼, 스택은 직관적인 구조를 제공합니다.

  • 빠른 삽입/삭제: 데이터 삽입(push)과 삭제(pop)는 O(1)의 시간 복잡도로 빠르게 처리할 수 있습니다. 마치 접시를 쌓거나 빼는 것처럼, 스택은 데이터 삽입/삭제가 빠릅니다.

  • 메모리 효율성: 데이터가 연속적으로 저장되므로 메모리 공간을 효율적으로 사용할 수 있습니다. 마치 퍼즐 조각처럼, 스택은 데이터를 메모리 공간에 촘촘하게 배치합니다.

단점

  • 접근 제한: 스택의 중간에 있는 데이터에는 직접 접근할 수 없습니다. 마치 탑의 중간에 있는 블록을 꺼내려면 위의 블록들을 모두 내려야 하는 것처럼, 스택은 중간 데이터 접근이 어렵습니다.

  • 크기 제한: 스택의 크기는 제한되어 있어 크기를 초과하는 데이터를 저장할 수 없습니다. 마치 정해진 공간의 창고처럼, 스택은 미리 지정된 크기 이상의 데이터를 담을 수 없습니다.

  • 오버플로우/언더플로우: 스택이 가득 찬 상태에서 데이터를 삽입하려고 하면 오버플로우(overflow)가 발생하고, 스택이 비어있는 상태에서 데이터를 삭제하려고 하면 언더플로우(underflow)가 발생할 수 있습니다. 마치 꽉 찬 접시 더미에 접시를 추가하거나, 빈 접시 더미에서 접시를 꺼내려고 하는 것처럼, 스택은 오버플로우/언더플로우에 주의해야 합니다.

스택(Stack)의 활용 분야


스택은 다양한 분야에서 활용됩니다.

  • 함수 호출 스택: 함수 호출 시 지역 변수, 매개변수, 반환 주소 등을 스택에 저장하여 함수의 실행 순서를 관리합니다.
  • 재귀 함수: 재귀 함수 호출 시 스택을 사용하여 함수 호출 정보를 저장합니다.
  • 웹 브라우저의 뒤로 가기: 사용자가 방문한 페이지를 스택에 저장하여 뒤로 가기 기능을 구현합니다.
  • 텍스트 편집기의 undo/redo: 사용자의 편집 작업을 스택에 저장하여 undo/redo 기능을 구현합니다.
  • 역사 시뮬레이션: 특정 시점의 상태를 스택에 저장하여 과거 시점으로 되돌리는 기능을 구현합니다.

문제점&주의사항


  • 크기 제한: 스택의 크기를 초과하는 데이터를 저장하려고 하면 오버플로우가 발생합니다. 따라서 스택을 사용할 때 적절한 크기를 지정해야 합니다. 마치 도시 계획처럼, 스택을 사용할 때는 데이터의 양을 미리 예측하고 적절한 크기를 할당해야 합니다.

  • 오버플로우/언더플로우: 스택이 가득 찬 상태에서 데이터를 삽입하거나, 스택이 비어있는 상태에서 데이터를 삭제하려고 하면 오버플로우/언더플로우가 발생할 수 있습니다. 따라서 스택의 상태를 확인하고 예외 처리를 해야 합니다. 마치 안전 점검처럼, 스택을 사용할 때는 오버플로우/언더플로우를 대비해야 합니다.

  • 메모리 관리: 더 이상 사용하지 않는 스택은 메모리에서 해제하여 메모리 누수를 방지해야 합니다. 마치 사용한 컵을 깨끗이 씻는 것처럼, 스택을 사용 후에는 메모리를 정리해야 합니다.

예제


C#에서는 Stack을 공식적으로 지원하지 않기 때문에 아래와 같이 System.Collections.Generic 를 추가해서 stack을 사용할 수 있습니다.

using System;
using System.Collections.Generic;

class StackSample
{
    static void Main(string[] args)
    {
        // 1. 스택 생성
        Stack<int> myStack = new Stack<int>();

        // 2. 데이터 삽입 (push)
        myStack.Push(10);
        myStack.Push(20);
        myStack.Push(30);

        // 3. 데이터 접근 (peek)
        Console.WriteLine("Peek: " + myStack.Peek()); // 30 출력 (가장 위의 데이터 확인)

        // 4. 데이터 삭제 (pop)
        Console.WriteLine("Pop: " + myStack.Pop()); // 30 출력 (가장 위의 데이터 삭제 후 반환)

        // 5. 스택 순회
        foreach (int value in myStack)
        {
            Console.WriteLine("Value: " + value); // 20, 10 출력 (LIFO 순서)
        }

        // 6. 스택 길이
        Console.WriteLine("Count: " + myStack.Count); // 2 출력

        // 7. 스택 비우기
        myStack.Clear();
    }
}


Top