λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°
Knowledge/Data structure

[자료ꡬ쑰]파이썬 μŠ€νƒ ꡬ쑰 μ™„λ²½ κ°€μ΄λ“œ: κ°œλ…, κ΅¬ν˜„ 및 ν™œμš© 예제

by YJ Dev 2024. 6. 18.
728x90
λ°˜μ‘ν˜•
SMALL

νŒŒμ΄μ¬μ—μ„œ μŠ€νƒ(Stack) κ΅¬μ‘°λŠ” 데이터 μ €μž₯ 및 μ ‘κ·Ό 방식 쀑 ν•˜λ‚˜λ‘œ, ν›„μž…μ„ μΆœ(LIFO: Last In, First Out) 원칙을 λ”°λ¦…λ‹ˆλ‹€. μ΄λŠ” λ§ˆμ§€λ§‰μ— μΆ”κ°€λœ ν•­λͺ©μ΄ κ°€μž₯ λ¨Όμ € μ œκ±°λ˜λŠ” ꡬ쑰둜, λΈŒλΌμš°μ €μ˜ λ’€λ‘œ κ°€κΈ° κΈ°λŠ₯μ΄λ‚˜ 호좜 μŠ€νƒ(Call Stack)μ—μ„œ ν”νžˆ λ³Ό 수 μžˆμŠ΅λ‹ˆλ‹€. 이번 ν¬μŠ€νŒ…μ—μ„œλŠ” νŒŒμ΄μ¬μ—μ„œ μŠ€νƒ ꡬ쑰의 κ°œλ…, κ΅¬ν˜„ 방법, 그리고 μ‹€μ „ ν™œμš© 예제λ₯Ό λ‹€λ£° κ²ƒμž…λ‹ˆλ‹€.

자료ꡬ쑰 μŠ€νƒ


μŠ€νƒμ€ λ°°μ—΄ ꡬ쑰둜 κ΅¬ν˜„λ˜λŠ”λ°, νŒŒμ΄μ¬μ—μ„œλŠ” 배열을 λ¦¬μŠ€νŠΈμ™€ νŠœν”Œμ„ 톡해 κ΅¬ν˜„ν•  수 μžˆμŠ΅λ‹ˆλ‹€. 배열은 자료 ꡬ쑰λ₯Ό κ΅¬ν˜„ν•˜λŠ” 데 ν•„μš”ν•œ μ›μ†Œλ“€μ„ λ³€κ²½ν•  수 μžˆμ–΄μ•Ό ν•˜λ―€λ‘œ, νŒŒμ΄μ¬μ—μ„œλŠ” 주둜 리슀트λ₯Ό μ‚¬μš©ν•©λ‹ˆλ‹€. λ¦¬μŠ€νŠΈλŠ” μ›μ†Œμ˜ μΆ”κ°€, 제거, λ³€κ²½ 등이 κ°€λŠ₯ν•˜λ©°, μ΄λŸ¬ν•œ μœ μ—°μ„± λ•Œλ¬Έμ— 자료 ꡬ쑰λ₯Ό κ΅¬ν˜„ν•  λ•Œ 많이 ν™œμš©λ©λ‹ˆλ‹€. νŠœν”Œμ€ 변경이 λΆˆκ°€λŠ₯ν•œ μ„±μ§ˆμ„ 가지고 μžˆμ–΄, 데이터가 λ³€κ²½λ˜μ§€ μ•ŠλŠ” μƒν™©μ—μ„œ μ‚¬μš©λ©λ‹ˆλ‹€.

파이썬의 λ¦¬μŠ€νŠΈμ™€ νŠœν”Œμ— λŒ€ν•œ μžμ„Έν•œ λ‚΄μš©μ€ μ•„λž˜ ν¬μŠ€νŒ…μ„ μ°Έκ³ ν•΄ μ£Όμ„Έμš”πŸ˜

" "

[Python]파이썬 μ»¬λ ‰μ…˜ μžλ£Œν˜•: λ¦¬μŠ€νŠΈμ™€ νŠœν”Œμ˜ ν™œμš©λ²•κ³Ό 차이점

python λ¦¬μŠ€νŠΈμ™€ νŠœν”Œμ€ μ»¬λ ‰μ…˜ μžλ£Œν˜•μœΌλ‘œ, 각각 λ³€κ²½ κ°€λŠ₯ν•œ(mutable)κ³Ό λ³€κ²½ λΆˆκ°€λŠ₯ν•œ(immutable) μ‹œν€€μŠ€λ₯Ό λ‚˜νƒ€λƒ…λ‹ˆλ‹€. μ΄λ“€μ˜ 차이와 각각의 νŠΉμ§•μ„ μžμ„Ένžˆ μ‚΄νŽ΄λ³΄λ©° λΉ„κ΅ν•΄λ³΄κ² μŠ΅λ‹ˆλ‹€.≣ λͺ©μ°¨μ»¬

creativevista.tistory.com


01. μŠ€νƒμ΄λž€?🧐

μŠ€νƒ(Stack)은 ν›„μž…μ„ μΆœ(LIFO: Last In, First Out) 원칙을 λ”°λ₯΄λŠ” μ„ ν˜• μžλ£Œκ΅¬μ‘°μž…λ‹ˆλ‹€. μ΄λŠ” λ§ˆμ§€λ§‰μ— μΆ”κ°€λœ ν•­λͺ©μ΄ κ°€μž₯ λ¨Όμ € μ œκ±°λ˜λŠ” ꡬ쑰둜, μƒλ‹¨μ—μ„œλ§Œ 데이터λ₯Ό μ‚½μž…ν•˜κ³  μ‚­μ œν•  수 μžˆμŠ΅λ‹ˆλ‹€. μŠ€νƒμ€ 컴퓨터 κ³Όν•™μ—μ„œ 맀우 μ€‘μš”ν•œ κ°œλ…μœΌλ‘œ, λ‹€μ–‘ν•œ μ•Œκ³ λ¦¬μ¦˜κ³Ό 데이터 처리 κ³Όμ •μ—μ„œ ν™œμš©λ©λ‹ˆλ‹€.

μŠ€νƒμ€ λ°μ΄ν„°μ˜ μž„μ‹œ μ €μž₯ 및 관리, ν•¨μˆ˜ 호좜의 μˆœμ„œ 관리, μˆ˜μ‹μ˜ κ΄„ν˜Έ 검사 λ“± λ‹€μ–‘ν•œ κ³³μ—μ„œ μ‚¬μš©λ©λ‹ˆλ‹€. μŠ€νƒμ„ μ΄ν•΄ν•˜κ³  ν™œμš©ν•˜λ©΄ μ•Œκ³ λ¦¬μ¦˜μ„ 효과적으둜 κ΅¬ν˜„ν•˜κ³  데이터 처리 과정을 κ°„λ‹¨ν•˜κ³  μ§κ΄€μ μœΌλ‘œ λ§Œλ“€ 수 μžˆμŠ΅λ‹ˆλ‹€.

자료ꡬ쑰 μŠ€νƒ

1-1. μŠ€νƒμ˜ μ—°μ‚°

μŠ€νƒμ€ 데이터λ₯Ό μˆœμ„œλŒ€λ‘œ μŒ“μ•„ μ˜¬λ¦¬λŠ” κ΅¬μ‘°μž…λ‹ˆλ‹€. 일반적인 μŠ€νƒμ˜ 연산은 λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€.

  • push: μŠ€νƒμ˜ 상단에 ν•­λͺ©μ„ μΆ”κ°€ν•©λ‹ˆλ‹€.
  • pop: μŠ€νƒμ˜ μƒλ‹¨μ—μ„œ ν•­λͺ©μ„ μ œκ±°ν•˜κ³  λ°˜ν™˜ν•©λ‹ˆλ‹€.

자료ꡬ쑰 μŠ€νƒμžλ£Œκ΅¬μ‘° μŠ€νƒ

μΆ”κ°€μ μœΌλ‘œ, μŠ€νƒμ˜ ν˜„μž¬ μƒνƒœλ₯Ό ν™•μΈν•˜κΈ° μœ„ν•œ 연산듀도 μžˆμŠ΅λ‹ˆλ‹€:

  • peek: μŠ€νƒμ˜ 상단에 μžˆλŠ” ν•­λͺ©μ„ μ œκ±°ν•˜μ§€ μ•Šκ³  λ°˜ν™˜ν•©λ‹ˆλ‹€.
  • is_empty: μŠ€νƒμ΄ λΉ„μ–΄ μžˆλŠ”μ§€ ν™•μΈν•©λ‹ˆλ‹€.
  • size: μŠ€νƒμ— μžˆλŠ” ν•­λͺ©μ˜ 개수λ₯Ό λ°˜ν™˜ν•©λ‹ˆλ‹€.
  • μ˜€λ²„ν”Œλ‘œ(Overflow): μŠ€νƒμ΄ 꽉 μ°¬ μƒνƒœμ—μ„œ μΆ”κ°€λ‘œ ν•­λͺ©μ„ μ‚½μž…ν•˜λ €κ³  ν•  λ•Œ λ°œμƒν•©λ‹ˆλ‹€.
  • μ–Έλ”ν”Œλ‘œ(Underflow): μŠ€νƒμ΄ λΉ„μ–΄ μžˆλŠ” μƒνƒœμ—μ„œ ν•­λͺ©μ„ μ œκ±°ν•˜λ €κ³  ν•  λ•Œ λ°œμƒν•©λ‹ˆλ‹€.

1-2. μŠ€νƒμ˜ ν™œμš© 예 : μ›Ή λΈŒλΌμš°μ €μ˜ μ΄μ „νŽ˜μ΄μ§€λ‘œ 이동

μ›Ή λΈŒλΌμš°μ €μ˜ λ’€λ‘œ κ°€κΈ° κΈ°λŠ₯은 μŠ€νƒμ„ μ΄μš©ν•˜μ—¬ κ΅¬ν˜„λ©λ‹ˆλ‹€. μ‚¬μš©μžκ°€ λ°©λ¬Έν•œ νŽ˜μ΄μ§€λ₯Ό μŠ€νƒμ— μ €μž₯ν•˜κ³ , 'λ’€λ‘œ κ°€κΈ°' λ²„νŠΌμ„ 클릭할 λ•Œλ§ˆλ‹€ μŠ€νƒμ˜ μƒλ‹¨μ—μ„œ νŽ˜μ΄μ§€λ₯Ό μ œκ±°ν•˜μ—¬ 이전 νŽ˜μ΄μ§€λ‘œ μ΄λ™ν•©λ‹ˆλ‹€.

1-3. 좔상 μžλ£Œν˜•

μŠ€νƒμ€ μΆ”μƒμžλ£Œν˜•(Abstract Data Type, ADT)으둜 μ •μ˜λ©λ‹ˆλ‹€. μ΄λŠ” μŠ€νƒμ˜ λ™μž‘μ„ μ •μ˜ν•˜λŠ” λͺ…세이며, 이λ₯Ό κ΅¬ν˜„ν•˜λŠ” λ‹€μ–‘ν•œ 방법이 μ‘΄μž¬ν•©λ‹ˆλ‹€. μΆ”μƒμžλ£Œν˜•μ€ κ΅¬ν˜„ μ„ΈλΆ€ 사항과 λ¬΄κ΄€ν•˜κ²Œ μŠ€νƒμ˜ λ™μž‘μ„ μ„€λͺ…ν•˜λŠ” 데 쀑점을 λ‘‘λ‹ˆλ‹€.


02. λ°°μ—΄κ΅¬μ‘°λ‘œ μŠ€νƒ κ΅¬ν˜„ν•˜κΈ°

μŠ€νƒμ€ λ°°μ—΄ κ΅¬μ‘°λ‚˜ μ—°κ²° 리슀트 ꡬ쑰λ₯Ό 톡해 κ΅¬ν˜„ν•  수 μžˆμŠ΅λ‹ˆλ‹€. μ—¬κΈ°μ„œλŠ” λ°°μ—΄ ꡬ쑰λ₯Ό μ‚¬μš©ν•˜μ—¬ μŠ€νƒμ„ κ΅¬ν˜„ν•˜λŠ” 방법에 λŒ€ν•΄ μ„€λͺ…ν•˜κ² μŠ΅λ‹ˆλ‹€.

2-1. 자료ꡬ쑰의 κ΅¬ν˜„ 방법듀 (배열ꡬ쑰, μ—°κ²°λœ ꡬ쑰)

  • 배열ꡬ쑰: κ³ μ •λœ 크기의 배열을 μ‚¬μš©ν•˜μ—¬ μŠ€νƒμ„ κ΅¬ν˜„ν•©λ‹ˆλ‹€. 이 방법은 κ΅¬ν˜„μ΄ κ°„λ‹¨ν•˜κ³ , 인덱슀λ₯Ό μ΄μš©ν•œ λΉ λ₯Έ 접근이 κ°€λŠ₯ν•©λ‹ˆλ‹€. κ·ΈλŸ¬λ‚˜ λ°°μ—΄μ˜ 크기가 κ³ μ •λ˜μ–΄ μžˆμ–΄ 크기λ₯Ό μ΄ˆκ³Όν•˜λ©΄ μŠ€νƒ μ˜€λ²„ν”Œλ‘œκ°€ λ°œμƒν•©λ‹ˆλ‹€.
  • μ—°κ²°λœ ꡬ쑰: μ—°κ²° 리슀트λ₯Ό μ‚¬μš©ν•˜μ—¬ μŠ€νƒμ„ κ΅¬ν˜„ν•©λ‹ˆλ‹€. 이 방법은 λ™μ μœΌλ‘œ 크기λ₯Ό μ‘°μ ˆν•  수 μžˆμ–΄ λ©”λͺ¨λ¦¬ νš¨μœ¨μ μ΄μ§€λ§Œ, λ…Έλ“œμ˜ μ—°κ²°κ³Ό ν•΄μ œμ— 좔가적인 μ‹œκ°„μ΄ μ†Œμš”λ©λ‹ˆλ‹€.

2-2. λ°°μ—΄ ꡬ쑰의 μŠ€νƒμ„ μœ„ν•œ 데이터

λ°°μ—΄ ꡬ쑰의 μŠ€νƒμ„ κ΅¬ν˜„ν•  λ•Œ, κ³ μ •λœ 크기의 배열을 μ‚¬μš©ν•˜μ—¬ μŠ€νƒμ˜ μš©λŸ‰(capacity)을 μ„€μ •ν•  수 μžˆμŠ΅λ‹ˆλ‹€. μ΄λ•Œ top λ³€μˆ˜λŠ” μŠ€νƒμ˜ ν˜„μž¬ 상단 μœ„μΉ˜λ₯Ό κ°€λ¦¬ν‚΅λ‹ˆλ‹€.

2-3. μŠ€νƒμ˜ μ—°μ‚°

μŠ€νƒμ—μ„œ μ‚¬μš©ν•  μ£Όμš” 연산은 λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€.

  • push: 리슀트의 끝에 ν•­λͺ©μ„ μΆ”κ°€ν•©λ‹ˆλ‹€.
  • pop: 리슀트의 λμ—μ„œ ν•­λͺ©μ„ μ œκ±°ν•˜κ³  λ°˜ν™˜ν•©λ‹ˆλ‹€.
  • peek: 리슀트의 끝에 μžˆλŠ” ν•­λͺ©μ„ μ œκ±°ν•˜μ§€ μ•Šκ³  λ°˜ν™˜ν•©λ‹ˆλ‹€.
  • is_empty: λ¦¬μŠ€νŠΈκ°€ λΉ„μ–΄ μžˆλŠ”μ§€ ν™•μΈν•©λ‹ˆλ‹€.
  • size: λ¦¬μŠ€νŠΈμ— μžˆλŠ” ν•­λͺ©μ˜ 개수λ₯Ό λ°˜ν™˜ν•©λ‹ˆλ‹€.

λ‹€μŒμ€ κ³ μ •λœ 크기의 배열을 μ‚¬μš©ν•˜μ—¬ μŠ€νƒμ„ κ΅¬ν˜„ν•œ μ˜ˆμ œμ™€ 데이터λ₯Ό μΆ”κ°€ν•˜κ³  μ œκ±°ν•˜λŠ” μ˜ˆμ œμž…λ‹ˆλ‹€.

class ArrayStack:
    def __init__(self, capacity=10):
        # μŠ€νƒμ˜ μš©λŸ‰μ„ μ„€μ •ν•˜κ³  배열을 μ΄ˆκΈ°ν™”ν•©λ‹ˆλ‹€.
        self.capacity = capacity
        self.array = [None] * capacity
        self.top = -1  # μŠ€νƒμ˜ 상단을 κ°€λ¦¬ν‚€λŠ” 포인터λ₯Ό μ΄ˆκΈ°ν™”ν•©λ‹ˆλ‹€.

    def is_empty(self):
        # μŠ€νƒμ΄ λΉ„μ–΄ μžˆλŠ”μ§€ ν™•μΈν•©λ‹ˆλ‹€.
        return self.top == -1

    def is_full(self):
        # μŠ€νƒμ΄ 가득 μ°ΌλŠ”μ§€ ν™•μΈν•©λ‹ˆλ‹€.
        return self.top == self.capacity - 1

    def push(self, item):
        # μŠ€νƒμ˜ 상단에 ν•­λͺ©μ„ μΆ”κ°€ν•©λ‹ˆλ‹€.
        if self.is_full():
            # μŠ€νƒμ΄ 가득 찼으면 μ˜ˆμ™Έλ₯Ό λ°œμƒμ‹œν‚΅λ‹ˆλ‹€.
            raise OverflowError("push to full stack")
        self.top += 1  # 상단 포인터λ₯Ό μ¦κ°€μ‹œν‚΅λ‹ˆλ‹€.
        self.array[self.top] = item  # μƒˆλ‘œμš΄ ν•­λͺ©μ„ 상단에 μΆ”κ°€ν•©λ‹ˆλ‹€.

    def pop(self):
        # μŠ€νƒμ˜ μƒλ‹¨μ—μ„œ ν•­λͺ©μ„ μ œκ±°ν•˜κ³  λ°˜ν™˜ν•©λ‹ˆλ‹€.
        if self.is_empty():
            # μŠ€νƒμ΄ λΉ„μ–΄ 있으면 μ˜ˆμ™Έλ₯Ό λ°œμƒμ‹œν‚΅λ‹ˆλ‹€.
            raise IndexError("pop from empty stack")
        item = self.array[self.top]  # μƒλ‹¨μ˜ ν•­λͺ©μ„ κ°€μ Έμ˜΅λ‹ˆλ‹€.
        self.array[self.top] = None  # μƒλ‹¨μ˜ ν•­λͺ©μ„ None으둜 μ„€μ •ν•˜μ—¬ μŠ¬λ‘―μ„ λΉ„μ›λ‹ˆλ‹€.
        self.top -= 1  # 상단 포인터λ₯Ό κ°μ†Œμ‹œν‚΅λ‹ˆλ‹€.
        return item  # μƒλ‹¨μ˜ ν•­λͺ©μ„ λ°˜ν™˜ν•©λ‹ˆλ‹€.

    def peek(self):
        # μŠ€νƒμ˜ 상단에 μžˆλŠ” ν•­λͺ©μ„ μ œκ±°ν•˜μ§€ μ•Šκ³  λ°˜ν™˜ν•©λ‹ˆλ‹€.
        if self.is_empty():
            # μŠ€νƒμ΄ λΉ„μ–΄ 있으면 μ˜ˆμ™Έλ₯Ό λ°œμƒμ‹œν‚΅λ‹ˆλ‹€.
            raise IndexError("peek from empty stack")
        return self.array[self.top]  # μƒλ‹¨μ˜ ν•­λͺ©μ„ λ°˜ν™˜ν•©λ‹ˆλ‹€.

    def size(self):
        # μŠ€νƒμ— μžˆλŠ” ν•­λͺ©μ˜ 개수λ₯Ό λ°˜ν™˜ν•©λ‹ˆλ‹€.
        return self.top + 1

# μŠ€νƒ μ‚¬μš© 예제
stack = ArrayStack(10)
stack.push(1)  # μŠ€νƒμ— 1을 μΆ”κ°€ν•©λ‹ˆλ‹€.
stack.push(2)  # μŠ€νƒμ— 2λ₯Ό μΆ”κ°€ν•©λ‹ˆλ‹€.
stack.push(3)  # μŠ€νƒμ— 3을 μΆ”κ°€ν•©λ‹ˆλ‹€.
print(stack.pop())  # 좜λ ₯: 3 (μŠ€νƒμ˜ μƒλ‹¨μ—μ„œ 3을 μ œκ±°ν•˜κ³  λ°˜ν™˜ν•©λ‹ˆλ‹€.)
print(stack.peek()) # 좜λ ₯: 2 (μŠ€νƒμ˜ 상단에 μžˆλŠ” 2λ₯Ό μ œκ±°ν•˜μ§€ μ•Šκ³  λ°˜ν™˜ν•©λ‹ˆλ‹€.)
print(stack.size()) # 좜λ ₯: 2 (μŠ€νƒμ— μžˆλŠ” ν•­λͺ©μ˜ 개수λ₯Ό λ°˜ν™˜ν•©λ‹ˆλ‹€.)

2-4. μŠ€νƒμ„ 클래슀둜 κ΅¬ν˜„

μžλ£Œκ΅¬μ‘°λŠ” ν•¨μˆ˜λ₯Ό 기반으둜 ν•˜λŠ” 절차적 ν”„λ‘œκ·Έλž˜λ°λ³΄λ‹€ 클래슀λ₯Ό 기반으둜 ν•˜λŠ” 객체 지ν–₯ ν”„λ‘œκ·Έλž˜λ° 기법을 μ΄μš©ν•΄ κ΅¬ν˜„ν•˜λŠ” 것이 훨씬 μ’‹μŠ΅λ‹ˆλ‹€. μ΄λŠ” 자료ꡬ쑰의 μΆ”μƒμžλ£Œν˜•μ΄ 클래슀의 κ°œλ…κ³Ό μ •ν™•νžˆ μΌμΉ˜ν•˜κΈ° λ•Œλ¬Έμž…λ‹ˆλ‹€. λ‹€μŒμ€ νŒŒμ΄μ¬μ—μ„œ λ°°μ—΄ ꡬ쑰λ₯Ό μ‚¬μš©ν•˜μ—¬ μŠ€νƒμ„ κ΅¬ν˜„ν•œ μ˜ˆμ œμž…λ‹ˆλ‹€.

class Stack:
    def __init__(self):
        self.items = []

    def is_empty(self):
        return len(self.items) == 0

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

    def pop(self):
        if not self.is_empty():
            return self.items.pop()
        else:
            raise IndexError("pop from empty stack")

    def peek(self):
        if not self.is_empty():
            return self.items[-1]
        else:
            raise IndexError("peek from empty stack")

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

κ΅¬ν˜„ν•œ μŠ€νƒ 클래슀λ₯Ό μ΄μš©ν•˜μ—¬ 데이터λ₯Ό μŠ€νƒμ— μΆ”κ°€ν•˜κ³  μ œκ±°ν•˜λŠ” μ˜ˆμ œλŠ” λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€.

# μŠ€νƒ μ‚¬μš© 예제
stack = Stack()
stack.push(1)
stack.push(2)
stack.push(3)
print(stack.pop())  # 좜λ ₯: 3
print(stack.peek()) # 좜λ ₯: 2
print(stack.size()) # 좜λ ₯: 2

이처럼 λ°°μ—΄ ꡬ쑰λ₯Ό μ‚¬μš©ν•œ μŠ€νƒ κ΅¬ν˜„μ€ κ°„λ‹¨ν•˜κ³  νš¨μœ¨μ μž…λ‹ˆλ‹€. 리슀트의 끝뢀뢄을 μŠ€νƒμ˜ μƒλ‹¨μœΌλ‘œ κ°„μ£Όν•˜μ—¬ 데이터λ₯Ό μΆ”κ°€ν•˜κ³  μ œκ±°ν•  수 μžˆμŠ΅λ‹ˆλ‹€.


03. μŠ€νƒμ˜ ν™œμš© 예제: κ΄„ν˜Έ 검사 ν”„λ‘œκ·Έλž¨

μŠ€νƒμ€ κ΄„ν˜Έμ˜ 짝이 λ§žλŠ”μ§€ ν™•μΈν•˜λŠ” λ¬Έμ œμ— μœ μš©ν•˜κ²Œ ν™œμš©λ  수 μžˆμŠ΅λ‹ˆλ‹€. 이 μ„Ήμ…˜μ—μ„œλŠ” μŠ€νƒμ„ μ‚¬μš©ν•˜μ—¬ κ΄„ν˜Έμ˜ 짝을 κ²€μ‚¬ν•˜λŠ” μ•Œκ³ λ¦¬μ¦˜κ³Ό 이λ₯Ό κ΅¬ν˜„ν•œ ν”„λ‘œκ·Έλž¨μ„ μ‚΄νŽ΄λ³΄κ² μŠ΅λ‹ˆλ‹€.

3-1. κ΄„ν˜Έ 검사 μ•Œκ³ λ¦¬μ¦˜

κ΄„ν˜Έ 검사 μ•Œκ³ λ¦¬μ¦˜μ€ λ¬Έμžμ—΄μ— μžˆλŠ” κ΄„ν˜Έλ“€μ΄ μ˜¬λ°”λ₯΄κ²Œ 짝지어져 μžˆλŠ”μ§€ ν™•μΈν•©λ‹ˆλ‹€. 이 μ•Œκ³ λ¦¬μ¦˜μ€ λ‹€μŒκ³Ό 같이 λ™μž‘ν•©λ‹ˆλ‹€:

  1. λ¬Έμžμ—΄μ„ μ²˜μŒλΆ€ν„° λκΉŒμ§€ μˆœνšŒν•©λ‹ˆλ‹€.
  2. μ—¬λŠ” κ΄„ν˜Έκ°€ λ‚˜μ˜€λ©΄ μŠ€νƒμ— push ν•©λ‹ˆλ‹€.
  3. λ‹«λŠ” κ΄„ν˜Έκ°€ λ‚˜μ˜€λ©΄ μŠ€νƒμ—μ„œ pop ν•˜μ—¬ 짝이 λ§žλŠ” μ—¬λŠ” κ΄„ν˜ΈμΈμ§€ ν™•μΈν•©λ‹ˆλ‹€.
  4. λ¬Έμžμ—΄μ˜ λκΉŒμ§€ κ²€μ‚¬ν–ˆμ„ λ•Œ μŠ€νƒμ΄ λΉ„μ–΄ 있으면 λͺ¨λ“  κ΄„ν˜Έκ°€ μ˜¬λ°”λ₯΄κ²Œ 짝지어져 μžˆλŠ” κ²ƒμž…λ‹ˆλ‹€.
  5. μŠ€νƒμ΄ λΉ„μ–΄ μžˆμ§€ μ•Šκ±°λ‚˜ 짝이 λ§žμ§€ μ•ŠλŠ” 경우, κ΄„ν˜Έκ°€ μ˜¬λ°”λ₯΄κ²Œ 짝지어져 μžˆμ§€ μ•Šμ€ κ²ƒμž…λ‹ˆλ‹€.

3-1. κ΄„ν˜Έ 검사 ν”„λ‘œκ·Έλž¨

λ‹€μŒμ€ νŒŒμ΄μ¬μ—μ„œ μŠ€νƒμ„ μ‚¬μš©ν•˜μ—¬ κ΄„ν˜Έμ˜ 짝을 κ²€μ‚¬ν•˜λŠ” ν”„λ‘œκ·Έλž¨μž…λ‹ˆλ‹€.

class Stack:
    def __init__(self):
        self.items = []

    def is_empty(self):
        return len(self.items) == 0

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

    def pop(self):
        if not self.is_empty():
            return self.items.pop()
        else:
            raise IndexError("pop from empty stack")

    def peek(self):
        if not self.is_empty():
            return self.items[-1]
        else:
            raise IndexError("peek from empty stack")

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

def is_balanced(expression):
    stack = Stack()
    # κ΄„ν˜Έμ˜ 짝을 λ§žμΆ”κΈ° μœ„ν•œ λ”•μ…”λ„ˆλ¦¬
    pairs = {')': '(', '}': '{', ']': '['}

    for char in expression:
        if char in pairs.values():
            # μ—¬λŠ” κ΄„ν˜Έλ₯Ό μŠ€νƒμ— μΆ”κ°€
            stack.push(char)
        elif char in pairs.keys():
            # λ‹«λŠ” κ΄„ν˜Έκ°€ λ‚˜μ˜€λ©΄ μŠ€νƒμ—μ„œ μ—¬λŠ” κ΄„ν˜Έλ₯Ό μ œκ±°ν•˜κ³  짝이 λ§žλŠ”μ§€ 확인
            if stack.is_empty() or stack.pop() != pairs[char]:
                return False

    # λͺ¨λ“  κ΄„ν˜Έκ°€ 짝이 λ§žλ‹€λ©΄ μŠ€νƒμ΄ λΉ„μ–΄ μžˆμ–΄μ•Ό 함
    return stack.is_empty()

# κ΄„ν˜Έ 검사 ν”„λ‘œκ·Έλž¨ μ‚¬μš© 예제
print(is_balanced("(a + b) * (c + d)"))  # 좜λ ₯: True
print(is_balanced("{[a + b] * (c + d)}"))  # 좜λ ₯: True
print(is_balanced("{[a + b] * (c + d)"))  # 좜λ ₯: False

μ£Όμš” ν•¨μˆ˜ μ„€λͺ…

  • is_balanced: 주어진 ν‘œν˜„μ‹μ˜ κ΄„ν˜Έκ°€ μ˜¬λ°”λ₯΄κ²Œ 짝지어져 μžˆλŠ”μ§€ ν™•μΈν•©λ‹ˆλ‹€.
    • expression: κ΄„ν˜Έμ˜ 짝을 검사할 λ¬Έμžμ—΄μž…λ‹ˆλ‹€.
    • stack: μŠ€νƒ μΈμŠ€ν„΄μŠ€λ₯Ό μƒμ„±ν•˜μ—¬ κ΄„ν˜Έλ₯Ό μ €μž₯ν•©λ‹ˆλ‹€.
    • pairs: λ‹«λŠ” κ΄„ν˜Έμ™€ μ—¬λŠ” κ΄„ν˜Έμ˜ 짝을 λ§žμΆ”κΈ° μœ„ν•œ λ”•μ…”λ„ˆλ¦¬μž…λ‹ˆλ‹€.
    • λ¬Έμžμ—΄μ„ μˆœνšŒν•˜λ©΄μ„œ μ—¬λŠ” κ΄„ν˜ΈλŠ” μŠ€νƒμ— push ν•˜κ³ , λ‹«λŠ” κ΄„ν˜ΈλŠ” μŠ€νƒμ—μ„œ pop ν•˜μ—¬ 짝이 λ§žλŠ”μ§€ ν™•μΈν•©λ‹ˆλ‹€.
    • λͺ¨λ“  κ΄„ν˜Έλ₯Ό κ²€μ‚¬ν•œ ν›„ μŠ€νƒμ΄ λΉ„μ–΄ 있으면 Trueλ₯Ό λ°˜ν™˜ν•˜κ³ , 그렇지 μ•ŠμœΌλ©΄ Falseλ₯Ό λ°˜ν™˜ν•©λ‹ˆλ‹€.

이 ν”„λ‘œκ·Έλž¨μ„ 톡해 λ¬Έμžμ—΄μ˜ κ΄„ν˜Έκ°€ μ˜¬λ°”λ₯΄κ²Œ 짝지어져 μžˆλŠ”μ§€ μ‰½κ²Œ 확인할 수 μžˆμŠ΅λ‹ˆλ‹€. κ΄„ν˜Έ 검사 μ•Œκ³ λ¦¬μ¦˜μ€ μ»΄νŒŒμΌλŸ¬μ—μ„œ μ½”λ“œμ˜ ꡬ문 였λ₯˜λ₯Ό κ²€μ‚¬ν•˜κ±°λ‚˜ ν…μŠ€νŠΈ μ—λ””ν„°μ—μ„œ κ΄„ν˜Έ 짝을 λ§žμΆ”λŠ” κΈ°λŠ₯ 등에 ν™œμš©λ  수 μžˆμŠ΅λ‹ˆλ‹€.


04. νŒŒμ΄μ¬μ—μ„œ μŠ€νƒ μ‚¬μš©ν•˜κΈ°

νŒŒμ΄μ¬μ—μ„œ μŠ€νƒμ„ μ‚¬μš©ν•˜λŠ” 방법은 μ—¬λŸ¬ 가지가 μžˆμŠ΅λ‹ˆλ‹€. 이 μ„Ήμ…˜μ—μ„œλŠ” 파이썬 리슀트λ₯Ό μŠ€νƒμœΌλ‘œ μ‚¬μš©ν•˜λŠ” 방법과 queue λͺ¨λ“ˆμ˜ LifoQueueλ₯Ό μ‚¬μš©ν•˜λŠ” 방법을 μ‚΄νŽ΄λ³΄κ² μŠ΅λ‹ˆλ‹€. 이 두 가지 방법을 톡해 νŒŒμ΄μ¬μ—μ„œ μŠ€νƒμ„ μ‰½κ²Œ κ΅¬ν˜„ν•˜κ³  μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€. 리슀트λ₯Ό μ‚¬μš©ν•˜λŠ” 방법은 κ°„λ‹¨ν•˜κ³  직관적이며, LifoQueueλ₯Ό μ‚¬μš©ν•˜λŠ” 방법은 μŠ€λ ˆλ“œ μ•ˆμ „μ„±μ„ μ œκ³΅ν•˜λ―€λ‘œ λ©€ν‹°μŠ€λ ˆλ”© ν™˜κ²½μ—μ„œ μœ μš©ν•©λ‹ˆλ‹€.

4-1. 파이썬 리슀트λ₯Ό μŠ€νƒμœΌλ‘œ μ‚¬μš©ν•˜κΈ°

파이썬의 리슀트 μžλ£Œν˜•μ€ μŠ€νƒμ˜ 연산을 μ‰½κ²Œ μ§€μ›ν•©λ‹ˆλ‹€. 리슀트의 append() λ©”μ„œλ“œλ‘œ push 연산을, pop() λ©”μ„œλ“œλ‘œ pop 연산을 μˆ˜ν–‰ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

λ‹€μŒμ€ 파이썬 리슀트λ₯Ό μ‚¬μš©ν•˜μ—¬ μŠ€νƒμ„ κ΅¬ν˜„ν•œ μ˜ˆμ œμž…λ‹ˆλ‹€.

class ListStack:
    def __init__(self):
        # μŠ€νƒμ„ κ΅¬ν˜„ν•˜κΈ° μœ„ν•΄ 빈 리슀트λ₯Ό μ΄ˆκΈ°ν™”ν•©λ‹ˆλ‹€.
        self.items = []

    def is_empty(self):
        # μŠ€νƒμ΄ λΉ„μ–΄ μžˆλŠ”μ§€ ν™•μΈν•©λ‹ˆλ‹€.
        return len(self.items) == 0

    def push(self, item):
        # μŠ€νƒμ˜ 상단에 ν•­λͺ©μ„ μΆ”κ°€ν•©λ‹ˆλ‹€.
        self.items.append(item)

    def pop(self):
        # μŠ€νƒμ˜ μƒλ‹¨μ—μ„œ ν•­λͺ©μ„ μ œκ±°ν•˜κ³  λ°˜ν™˜ν•©λ‹ˆλ‹€.
        if not self.is_empty():
            return self.items.pop()
        else:
            # μŠ€νƒμ΄ λΉ„μ–΄ 있으면 μ˜ˆμ™Έλ₯Ό λ°œμƒμ‹œν‚΅λ‹ˆλ‹€.
            raise IndexError("pop from empty stack")

    def peek(self):
        # μŠ€νƒμ˜ 상단에 μžˆλŠ” ν•­λͺ©μ„ μ œκ±°ν•˜μ§€ μ•Šκ³  λ°˜ν™˜ν•©λ‹ˆλ‹€.
        if not self.is_empty():
            return self.items[-1]
        else:
            # μŠ€νƒμ΄ λΉ„μ–΄ 있으면 μ˜ˆμ™Έλ₯Ό λ°œμƒμ‹œν‚΅λ‹ˆλ‹€.
            raise IndexError("peek from empty stack")

    def size(self):
        # μŠ€νƒμ— μžˆλŠ” ν•­λͺ©μ˜ 개수λ₯Ό λ°˜ν™˜ν•©λ‹ˆλ‹€.
        return len(self.items)

# 리슀트λ₯Ό μ‚¬μš©ν•œ μŠ€νƒ μ‚¬μš© 예제
stack = ListStack()
stack.push(1)  # μŠ€νƒμ— 1을 μΆ”κ°€ν•©λ‹ˆλ‹€.
stack.push(2)  # μŠ€νƒμ— 2λ₯Ό μΆ”κ°€ν•©λ‹ˆλ‹€.
stack.push(3)  # μŠ€νƒμ— 3을 μΆ”κ°€ν•©λ‹ˆλ‹€.
print(stack.pop())  # 좜λ ₯: 3 (μŠ€νƒμ˜ μƒλ‹¨μ—μ„œ 3을 μ œκ±°ν•˜κ³  λ°˜ν™˜ν•©λ‹ˆλ‹€.)
print(stack.peek()) # 좜λ ₯: 2 (μŠ€νƒμ˜ 상단에 μžˆλŠ” 2λ₯Ό μ œκ±°ν•˜μ§€ μ•Šκ³  λ°˜ν™˜ν•©λ‹ˆλ‹€.)
print(stack.size()) # 좜λ ₯: 2 (μŠ€νƒμ— μžˆλŠ” ν•­λͺ©μ˜ 개수λ₯Ό λ°˜ν™˜ν•©λ‹ˆλ‹€.)

μ£Όμš” λ©”μ„œλ“œ μ„€λͺ…

이 μ½”λ“œμ—μ„œλŠ” Stack 클래슀λ₯Ό μ •μ˜ν•˜κ³ , 파이썬의 리슀트λ₯Ό λ‚΄λΆ€μ μœΌλ‘œ μ‚¬μš©ν•˜μ—¬ μŠ€νƒμ„ κ΅¬ν˜„ν•˜μ˜€μŠ΅λ‹ˆλ‹€. 각 λ©”μ„œλ“œμ˜ 역할은 λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€.

  • __init__() λ©”μ„œλ“œ: μŠ€νƒμ„ μ΄ˆκΈ°ν™”ν•©λ‹ˆλ‹€. μ—¬κΈ°μ„œλŠ” λΉ„μ–΄ μžˆλŠ” 리슀트λ₯Ό self.items에 μ €μž₯ν•©λ‹ˆλ‹€.
  • is_empty() λ©”μ„œλ“œ: μŠ€νƒμ΄ λΉ„μ–΄ μžˆλŠ”μ§€ μ—¬λΆ€λ₯Ό λ°˜ν™˜ν•©λ‹ˆλ‹€. 리슀트의 길이가 0이면 λΉ„μ–΄ μžˆλŠ” κ²ƒμœΌλ‘œ νŒλ‹¨ν•©λ‹ˆλ‹€.
  • isFull(): 파이썬 λ¦¬μŠ€νŠΈλŠ” μš©λŸ‰μ΄ λ¬΄ν•œλŒ€μ΄λ―€λ‘œ μŠ€νƒμ˜ ν¬ν™”μƒνƒœλŠ” μ˜λ―Έκ°€ μ—†μœΌλ©° 항상 falseμž…λ‹ˆλ‹€.
  • push(item) λ©”μ„œλ“œ: μŠ€νƒμ˜ 맨 μœ„μ— 데이터λ₯Ό μΆ”κ°€ν•©λ‹ˆλ‹€. 리슀트의 append() λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•˜μ—¬ κ΅¬ν˜„ν•©λ‹ˆλ‹€.
  • pop() λ©”μ„œλ“œ: μŠ€νƒμ˜ 맨 μœ„μ—μ„œ 데이터λ₯Ό μ œκ±°ν•˜κ³  λ°˜ν™˜ν•©λ‹ˆλ‹€. 리슀트의 pop() λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•˜λ©°, μŠ€νƒμ΄ λΉ„μ–΄ μžˆλŠ” 경우 IndexErrorλ₯Ό λ°œμƒμ‹œν‚΅λ‹ˆλ‹€.
  • peek() λ©”μ„œλ“œ: μŠ€νƒμ˜ 맨 μœ„μ— μžˆλŠ” 데이터λ₯Ό λ°˜ν™˜ν•˜μ§€λ§Œ μ œκ±°ν•˜μ§€λŠ” μ•ŠμŠ΅λ‹ˆλ‹€. 리슀트의 인덱슀 -1(리슀트의 λ§ˆμ§€λ§‰ μš”μ†Œλ₯Ό 음수둜 ν‘œν˜„)을 μ‚¬μš©ν•˜μ—¬ κ΅¬ν˜„ν•˜λ©°, μŠ€νƒμ΄ λΉ„μ–΄ μžˆλŠ” 경우 IndexErrorλ₯Ό λ°œμƒμ‹œν‚΅λ‹ˆλ‹€.
  • size() λ©”μ„œλ“œ: μŠ€νƒμ— μ €μž₯된 λ°μ΄ν„°μ˜ 개수λ₯Ό λ°˜ν™˜ν•©λ‹ˆλ‹€. 리슀트의 길이λ₯Ό λ°˜ν™˜ν•©λ‹ˆλ‹€.

4-2. queue λͺ¨λ“ˆμ˜ LifoQueue μ‚¬μš©ν•˜κΈ°

파이썬의 queue λͺ¨λ“ˆμ—μ„œλŠ” LifoQueue 클래슀λ₯Ό μ œκ³΅ν•˜μ—¬ μŠ€νƒμ„ κ°„νŽΈν•˜κ²Œ κ΅¬ν˜„ν•  수 μžˆμŠ΅λ‹ˆλ‹€. 이λ₯Ό 톡해 좔가적인 μŠ€νƒ κ΅¬ν˜„ 없이도 λ‹€μ–‘ν•œ 문제λ₯Ό ν•΄κ²°ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

λ‹€μŒμ€ queue λͺ¨λ“ˆμ˜ LifoQueueλ₯Ό μ‚¬μš©ν•œ μ˜ˆμ œμž…λ‹ˆλ‹€.

from queue import LifoQueue

# LifoQueue 객체 생성
stack = LifoQueue()

# 데이터 μΆ”κ°€ (push)
stack.put(1)
stack.put(2)
stack.put(3)

# μŠ€νƒμ˜ 크기 확인
print("μŠ€νƒμ˜ 크기:", stack.qsize())

# 데이터 제거 및 λ°˜ν™˜ (pop)
print("pop:", stack.get())

# μŠ€νƒμ˜ 크기 λ‹€μ‹œ 확인
print("μŠ€νƒμ˜ 크기:", stack.qsize())

# peek κΈ°λŠ₯ κ΅¬ν˜„ (맨 μœ„ 데이터 확인)
def peek(stack):
    if not stack.empty():
        top_element = stack.get()
        stack.put(top_element)
        return top_element
    else:
        raise IndexError("peek from empty stack")

# peek ν•¨μˆ˜ μ‚¬μš© 예제
print("peek:", peek(stack))

# μŠ€νƒμ˜ 크기 확인 (peek ν•¨μˆ˜λŠ” 데이터λ₯Ό μ œκ±°ν•˜μ§€ μ•ŠμŒ)
print("μŠ€νƒμ˜ 크기:", stack.qsize())

μ£Όμš” λ©”μ„œλ“œ μ„€λͺ…

μœ„ μ˜ˆμ œμ—μ„œλŠ” LifoQueue 객체λ₯Ό μƒμ„±ν•˜κ³ , put() λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•˜μ—¬ 데이터λ₯Ό μŠ€νƒμ— μΆ”κ°€ν•˜κ³ (push), get() λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•˜μ—¬ 데이터λ₯Ό μŠ€νƒμ—μ„œ μ œκ±°ν•˜κ³  λ°˜ν™˜ν•©λ‹ˆλ‹€(pop). μŠ€νƒμ˜ ν˜„μž¬ 크기λ₯Ό ν™•μΈν•˜κΈ° μœ„ν•΄ qsize() λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

λ˜ν•œ, peek() λ©”μ„œλ“œλŠ” LifoQueue ν΄λž˜μŠ€μ— μ§μ ‘μ μœΌλ‘œ ν¬ν•¨λ˜μ–΄ μžˆμ§€ μ•ŠκΈ° λ•Œλ¬Έμ—, λ³„λ„λ‘œ ν•¨μˆ˜λ₯Ό μ •μ˜ν•˜μ—¬ μŠ€νƒμ˜ 맨 μœ„ 데이터λ₯Ό ν™•μΈν•˜λŠ” κΈ°λŠ₯을 κ΅¬ν˜„ν–ˆμŠ΅λ‹ˆλ‹€. 이 ν•¨μˆ˜λŠ” μŠ€νƒμ—μ„œ 데이터λ₯Ό μ œκ±°ν•˜μ§€ μ•Šκ³  μ‘°νšŒν•˜λŠ” λ°©μ‹μœΌλ‘œ λ™μž‘ν•©λ‹ˆλ‹€.


05. μ‹œμŠ€ν…œμŠ€νƒκ³Ό μˆœν™˜ν˜ΈμΆœ

μ‹œμŠ€ν…œμŠ€νƒ(System Stack)κ³Ό μˆœν™˜ν˜ΈμΆœ(Recursion)은 ν”„λ‘œκ·Έλž˜λ°μ—μ„œ μ€‘μš”ν•œ κ°œλ…μž…λ‹ˆλ‹€. 각각의 κ°œλ…μ„ κ°„λ‹¨νžˆ μ„€λͺ…ν•˜κ³ , μ–΄λ–»κ²Œ μƒν˜Έμž‘μš©ν•˜λŠ”μ§€μ— λŒ€ν•΄ μ•Œμ•„λ³΄κ² μŠ΅λ‹ˆλ‹€.

5-1. μ‹œμŠ€ν…œμŠ€νƒ(System Stack)

μ‹œμŠ€ν…œμŠ€νƒμ€ ν•¨μˆ˜ ν˜ΈμΆœμ„ κ΄€λ¦¬ν•˜κΈ° μœ„ν•΄ μ‚¬μš©λ˜λŠ” λ©”λͺ¨λ¦¬ μ˜μ—­μž…λ‹ˆλ‹€. 일반적으둜 각 ν•¨μˆ˜ ν˜ΈμΆœμ€ μŠ€νƒ λ©”λͺ¨λ¦¬μ— ν”„λ ˆμž„(Frame)이라고 λΆˆλ¦¬λŠ” 데이터 ꡬ쑰둜 μ €μž₯λ©λ‹ˆλ‹€. 각 ν”„λ ˆμž„μ€ ν•¨μˆ˜μ˜ 인수, 둜컬 λ³€μˆ˜ 및 ν•¨μˆ˜κ°€ λ°˜ν™˜λ  μœ„μΉ˜ λ“±μ˜ 정보λ₯Ό ν¬ν•¨ν•©λ‹ˆλ‹€.

μ‹œμŠ€ν…œμŠ€νƒμ˜ μ£Όμš” νŠΉμ„±μ€ λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€:

  • LIFO (Last In, First Out): ν•¨μˆ˜ 호좜이 μŠ€νƒμ— μŒ“μ΄κ³ , κ°€μž₯ μ΅œκ·Όμ— 호좜된 ν•¨μˆ˜κ°€ κ°€μž₯ λ¨Όμ € λ°˜ν™˜λ©λ‹ˆλ‹€.
  • μž¬κ·€ 호좜 관리: μž¬κ·€ ν•¨μˆ˜ 호좜 μ‹œ 각 μž¬κ·€ ν˜ΈμΆœμ€ μƒˆλ‘œμš΄ ν”„λ ˆμž„μ„ μ‹œμŠ€ν…œμŠ€νƒμ— μΆ”κ°€ν•©λ‹ˆλ‹€. 이λ₯Ό 톡해 μž¬κ·€ 호좜이 κΉŠμ–΄μ§ˆ λ•Œλ§ˆλ‹€ μ‹œμŠ€ν…œμŠ€νƒλ„ 그에 맞게 μ¦κ°€ν•©λ‹ˆλ‹€.

μ‹œμŠ€ν…œμŠ€νƒμ˜ ν¬κΈ°λŠ” μ œν•œλ˜μ–΄ 있기 λ•Œλ¬Έμ—, λ„ˆλ¬΄ λ§Žμ€ μž¬κ·€ ν˜ΈμΆœμ΄λ‚˜ λ„ˆλ¬΄ κΉŠμ€ μž¬κ·€ ν˜ΈμΆœμ€ μŠ€νƒ μ˜€λ²„ν”Œλ‘œμš°(Stack Overflow)λ₯Ό μΌμœΌν‚¬ 수 μžˆμŠ΅λ‹ˆλ‹€. μ΄λŠ” μŠ€νƒμ΄ μ΅œλŒ€ μš©λŸ‰μ„ μ΄ˆκ³Όν•˜μ—¬ μ‹œμŠ€ν…œμ΄ 더 이상 ν•¨μˆ˜ ν˜ΈμΆœμ„ μ²˜λ¦¬ν•  수 μ—†κ²Œ λ˜λŠ” 상황을 λ§ν•©λ‹ˆλ‹€.

5-2. μˆœν™˜ν˜ΈμΆœ(Recursion)

μˆœν™˜ν˜ΈμΆœμ€ ν•¨μˆ˜κ°€ 자기 μžμ‹ μ„ 직접 λ˜λŠ” κ°„μ ‘μ μœΌλ‘œ ν˜ΈμΆœν•˜λŠ” 것을 λ§ν•©λ‹ˆλ‹€. μ΄λŠ” λ‹€μ–‘ν•œ μ•Œκ³ λ¦¬μ¦˜κ³Ό 문제 ν•΄κ²° λ°©λ²•μ—μ„œ μœ μš©ν•˜κ²Œ μ‚¬μš©λ©λ‹ˆλ‹€. μ£Όμš” νŠΉμ„±μ€ λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€:

  • κΈ°λ³Έ 사둀(Base case): μž¬κ·€ ν•¨μˆ˜λŠ” μžμ‹ μ„ 계속 ν˜ΈμΆœν•˜λŠ”λ°, 이λ₯Ό λ©ˆμΆ”κΈ° μœ„ν•œ μ’…λ£Œ 쑰건이 ν•„μš”ν•©λ‹ˆλ‹€. 이 μ’…λ£Œ 쑰건을 κΈ°λ³Έ 사둀라고 ν•©λ‹ˆλ‹€.
  • μž¬κ·€ 사둀(Recursive case): κΈ°λ³Έ 사둀λ₯Ό λ§Œμ‘±ν•˜μ§€ μ•Šμ„ λ•Œ μžμ‹ μ„ ν˜ΈμΆœν•˜μ—¬ μž‘μ€ 문제둜 λΆ„ν•΄ν•˜κ³  ν•΄κ²°ν•©λ‹ˆλ‹€.
  • μŠ€νƒμ„ μ‚¬μš©ν•œ κ΅¬ν˜„: λŒ€λΆ€λΆ„μ˜ ν”„λ‘œκ·Έλž˜λ° μ–Έμ–΄μ—μ„œ μž¬κ·€ ν˜ΈμΆœμ€ λ‚΄λΆ€μ μœΌλ‘œ μ‹œμŠ€ν…œμŠ€νƒμ„ μ‚¬μš©ν•˜μ—¬ κ΅¬ν˜„λ©λ‹ˆλ‹€. 각 μž¬κ·€ ν˜ΈμΆœμ€ μƒˆλ‘œμš΄ ν”„λ ˆμž„μ„ μ‹œμŠ€ν…œμŠ€νƒμ— μΆ”κ°€ν•˜κ²Œ λ©λ‹ˆλ‹€.

5-3. μ‹œμŠ€ν…œμŠ€νƒκ³Ό μˆœν™˜ν˜ΈμΆœμ˜ μƒν˜Έμž‘μš©

μž¬κ·€ ν˜ΈμΆœμ„ μ‚¬μš©ν•˜λ©΄, μ‹œμŠ€ν…œμŠ€νƒμ— μ—¬λŸ¬ 개의 μž¬κ·€ 호좜 ν”„λ ˆμž„μ΄ μ°¨λ‘€λ‘œ μŒ“μ΄κ²Œ λ©λ‹ˆλ‹€. 각 μž¬κ·€ ν˜ΈμΆœμ€ μžμ‹ μ˜ ν”„λ ˆμž„μ„ μŠ€νƒμ— μΆ”κ°€ν•˜κ³ , κΈ°λ³Έ 사둀가 λ‚˜νƒ€λ‚  λ•ŒκΉŒμ§€ κ³„μ†ν•΄μ„œ μƒˆλ‘œμš΄ ν”„λ ˆμž„μ„ μΆ”κ°€ν•˜κ²Œ λ©λ‹ˆλ‹€. μž¬κ·€ 호좜이 κΉŠμ–΄μ§€λ©΄ μ‹œμŠ€ν…œμŠ€νƒλ„ 그에 맞게 κΉŠμ–΄μ§€κ²Œ λ©λ‹ˆλ‹€.

예λ₯Ό λ“€μ–΄, νŒ©ν† λ¦¬μ–Όμ„ κ΅¬ν•˜λŠ” μž¬κ·€ ν•¨μˆ˜λ₯Ό μ‚΄νŽ΄λ³΄λ©΄

def factorial(n):
    if n == 0:
        return 1
    else:
        return n * factorial(n - 1)

이 ν•¨μˆ˜λŠ” μžμ‹ μ„ 계속 ν˜ΈμΆœν•˜μ—¬ νŒ©ν† λ¦¬μ–Ό 값을 κ³„μ‚°ν•©λ‹ˆλ‹€. 호좜이 κΉŠμ–΄μ§ˆμˆ˜λ‘ μ‹œμŠ€ν…œμŠ€νƒλ„ 그에 맞게 κΉŠμ–΄μ§€κ²Œ λ©λ‹ˆλ‹€. λ”°λΌμ„œ μž¬κ·€ ν˜ΈμΆœμ„ μ‚¬μš©ν•  λ•ŒλŠ” μ‹œμŠ€ν…œμŠ€νƒμ˜ 크기 μ œν•œμ„ κ³ λ €ν•˜μ—¬ μŠ€νƒ μ˜€λ²„ν”Œλ‘œμš°λ₯Ό 방지할 ν•„μš”κ°€ μžˆμŠ΅λ‹ˆλ‹€.

결둠적으둜, μ‹œμŠ€ν…œμŠ€νƒκ³Ό μˆœν™˜ν˜ΈμΆœμ€ ν”„λ‘œκ·Έλž˜λ°μ—μ„œ μ€‘μš”ν•œ κ°œλ…μ΄λ©°, μž¬κ·€ ν˜ΈμΆœμ„ 톡해 μŠ€νƒμ„ ν™œμš©ν•˜λŠ” 것은 λ‹€μ–‘ν•œ μ•Œκ³ λ¦¬μ¦˜ 및 문제 해결에 μœ μš©ν•˜κ²Œ μ‚¬μš©λ©λ‹ˆλ‹€.


06. 핡심 λ‚΄μš©πŸ‘€

자료ꡬ쑰 μŠ€νƒ

728x90
λ°˜μ‘ν˜•