본문 바로가기
Computer Science/Data Structure

[DataStructure/Kotlin] 스택 구현: MutableList vs Array의 차이점과 구현 방법

by quessr 2025. 1. 17.

 

스택(Stack)은 데이터를 후입선출(LIFO, Last In First Out) 방식으로 저장하는 자료 구조입니다.

코틀린에서 스택을 구현할 때 주로 사용하는 두 가지 주요 데이터 구조는 MutableListArray입니다.

이번 글에서는 두 가지 방법으로 스택을 구현하는 코드와 함께, 각 방식의 차이점과 특징을 비교해보겠습니다.


1. MutableList를 사용한 스택 구현

MutableList는 코틀린의 동적 리스트로, 크기를 필요에 따라 자동으로 확장하거나 축소할 수 있습니다.

이를 사용하면 스택을 간단하고 유연하게 구현할 수 있습니다.

코드 예제:

val stack = mutableListOf<Int>()

fun push(data: Int) {
    stack.add(data) // 스택의 끝에 데이터 추가
}

fun pop(): Int {
    return if (stack.isNotEmpty()) stack.removeAt(stack.size - 1) else -1
}

fun size(): Int {
    return stack.size
}

fun empty(): Int {
    return if (stack.isEmpty()) 1 else 0
}

fun top(): Int {
    return if (stack.isNotEmpty()) stack.last() else -1
}

주요 특징:

  • 동적 크기 관리: MutableList는 크기를 신경 쓸 필요 없이 자동으로 확장됩니다.
  • 간결한 메서드 지원:
    • add()로 데이터 추가.
    • removeAt()으로 끝에서 데이터를 제거하고 반환.
    • last()로 마지막 요소를 확인.
  • 코드 간결성: top 변수를 따로 관리하지 않아도 stack.size로 상태를 바로 파악할 수 있습니다.

2. Array를 사용한 스택 구현

Array는 고정된 크기를 가지는 자료 구조로, 생성 시 크기를 미리 지정해야 합니다. 배열을 사용한 스택에서는 top 변수를 이용해 현재 스택의 위치를 추적합니다.

코드 예제:

val MAX_SIZE = 10000
val stack = Array(MAX_SIZE) { 0 }
var top = -1

fun push(data: Int) {
    if (top < MAX_SIZE - 1) {
        top++
        stack[top] = data
    } else {
        println("Stack Overflow")
    }
}

fun pop(): Int {
    return if (top >= 0) {
        val data = stack[top]
        top--
        data
    } else {
        -1
    }
}

fun size(): Int {
    return top + 1
}

fun empty(): Int {
    return if (top == -1) 1 else 0
}

fun top(): Int {
    return if (top >= 0) stack[top] else -1
}

주요 특징:

  • 고정 크기 관리: 배열은 생성 시 크기가 고정되며, 초과 시 별도 처리가 필요합니다.
  • top 변수: 배열에서 현재 위치를 관리하며, 데이터를 추가/제거할 때 top을 사용해 직접 인덱스를 추적합니다.
  • 직접 접근: stack[top]으로 데이터를 추가하거나 읽을 수 있습니다.

3. MutableList와 Array의 차이점

특징 MutableList Array
크기 동적 (자동 확장 가능) 고정 (생성 시 크기 지정 필요)
데이터 추가 add() 메서드로 자동 추가 top 변수를 이용해 인덱스에 직접 추가
데이터 제거 removeAt()으로 요소 제거 및 반환 top을 감소시켜 직접 관리
효율성 메모리 자동 관리 (약간의 오버헤드 발생) 메모리 고정, 관리 필요
코드 간결성 간단하고 직관적인 구현 가능 추가 로직 및 변수 관리 필요
오류 가능성 크기 초과 위험 없음 크기 초과 시 별도 처리 필요

 

4. 왜 두 가지 구현 방식이 다른가?

MutableList와 Array의 근본적인 차이

  • MutableList:
    • 크기가 동적으로 변경되며, 리스트의 메서드를 사용해 데이터를 쉽게 추가/제거할 수 있습니다.
    • 리스트의 크기(stack.size) 자체가 스택의 상태를 나타내므로 top 변수가 필요 없습니다.
  • Array:
    • 크기가 고정되며, 데이터를 추가/제거할 때 현재 위치를 추적하는 top 변수가 필요합니다.
    • 배열은 특정 인덱스에 바로 접근할 수 있지만, 크기 초과에 대한 처리가 필요합니다.

왜 Array 방식에서는 top 변수가 필요할까?

  • 배열은 크기가 고정되어 있어, 데이터가 저장될 위치를 명확히 관리해야 합니다.
  • top은 현재 스택의 최상단 요소를 추적하는 역할을 하며, 이를 통해 데이터를 추가(push)하거나 제거(pop)할 수 있습니다.

왜 MutableList에서는 top 변수가 필요하지 않을까?

  • MutableList는 동적 크기 관리로 인해 리스트의 끝에 데이터를 추가하거나 제거할 수 있습니다.
  • 스택의 상태를 나타내기 위해 리스트의 크기(stack.size - 1)를 활용할 수 있으므로 top을 별도로 관리할 필요가 없습니다.

 

5. MutableList와 Array의 사용 시나리오

MutableList가 적합한 경우

  • 스택 크기가 동적으로 변해야 할 때: 크기 제한 없이 데이터를 추가할 수 있어야 할 경우.
  • 간단한 구현이 필요할 때: 코드 작성과 유지보수가 간편해야 하는 경우.

Array가 적합한 경우

  • 스택 크기가 고정되어 있는 경우: 알고리즘 문제에서 스택의 크기가 명확히 제한되는 경우.
  • 메모리를 엄격히 관리해야 할 때: 메모리를 고정 크기로 관리해야 하는 경우(예: 임베디드 시스템).
  • 성능이 중요한 경우: 동적 메모리 할당보다 고정 크기 배열을 사용하는 것이 빠릅니다.

 

6. 결론

  • MutableList는 크기 제한 없이 간단하고 유연하게 스택을 구현할 수 있는 자료 구조로, 일반적인 코틀린 프로젝트에서 가장 적합합니다.
  • Array는 고정 크기의 데이터를 처리하거나 메모리 관리를 엄격히 해야 하는 경우에 유용합니다. 그러나 추가적인 로직(top 변수 관리 등)이 필요합니다.

요약:

  • top 변수는 고정 크기 배열(Array)에서 현재 위치를 추적하기 위해 필요하며, MutableList에서는 크기 관리가 자동으로 이루어지기 때문에 불필요합니다.
반응형