Swift 제네릭과 고급 데이터 구조: 제네릭을 활용한 링크드 리스트와 트리 같은 커스텀 데이터 구조 생성.

작성일 :

Swift 제네릭과 고급 데이터 구조: 제네릭을 활용한 링크드 리스트와 트리 같은 커스텀 데이터 구조 생성

Swift 언어는 강력하고 유연한 제네릭 시스템을 제공합니다. 제네릭을 활용하면 다양한 데이터 타입을 처리하는 코드의 중복을 줄일 수 있습니다. 이번 글에서는 Swift의 제네릭을 사용하여 링크드 리스트와 트리와 같은 커스텀 데이터 구조를 생성하는 방법을 알아보겠습니다.

제네릭의 기본 개념

제네릭은 타입에 의존하지 않는 코드 작성 방식을 의미합니다. 즉, 구체적인 데이터 타입에 구애받지 않고 함수나 데이터 구조를 정의할 수 있습니다. 예를 들어, 제네릭을 사용하여 숫자나 문자열 모두를 처리할 수 있는 함수를 작성할 수 있습니다.

swift
func swapTwoValues<T>(_ a: inout T, _ b: inout T) {
    let temporaryA = a
    a = b
    b = temporaryA
}

위 예제에서 swapTwoValues 함수는 두 개의 값을 입력받아 서로 교환합니다. 여기서 는 타입 매개변수로, 함수 호출 시 구체적인 타입으로 대체됩니다. 이로 인해 코드의 재사용성이 높아지고 유연성이 극대화됩니다.

링크드 리스트 구현

링크드 리스트는 데이터 요소가 각 요소의 주소를 포함하고 있는 포인터를 사용하여 연결된 선형 데이터 구조입니다. Swift에서 제네릭을 사용하여 링크드 리스트를 구현하는 방법을 보겠습니다.

swift
class Node<T> {
    var value: T
    var next: Node<T>?
    init(value: T) {
        self.value = value
    }
}

class LinkedList<T> {
    private var head: Node<T>?
    func append(value: T) {
        let newNode = Node(value: value)
        if let lastNode = getLastNode() {
            lastNode.next = newNode
        } else {
            head = newNode
        }
    }
    private func getLastNode() -> Node<T>? {
        var node = head
        while node?.next != nil {
            node = node?.next
        }
        return node
    }
}

위의 코드에서 Node 클래스와 LinkedList 클래스는 제네릭 타입 T를 사용하여 구현되었습니다. 이런 방식으로 링크드 리스트를 만들면 문자열, 정수 등 다양한 타입의 데이터를 저장할 수 있습니다.

트리 구조 구현

트리는 각 노드가 여러 하위 노드를 가질 수 있는 비선형 데이터 구조입니다. Swift의 제네릭을 사용하여 이진 트리(binary tree)를 구현하는 예제를 보겠습니다.

swift
class TreeNode<T> {
    var value: T
    var leftChild: TreeNode?
    var rightChild: TreeNode?
    init(value: T) {
        self.value = value
    }
}

class BinaryTree<T> {
    var root: TreeNode<T>?
    func insert(value: T) {
        let newNode = TreeNode(value: value)
        if root == nil {
            root = newNode
        } else {
            var queue: [TreeNode<T>] = [root!]
            while !queue.isEmpty {
                let node = queue.removeFirst()
                if node.leftChild == nil {
                    node.leftChild = newNode
                    return
                } else if node.rightChild == nil {
                    node.rightChild = newNode
                    return
                } else {
                    queue.append(node.leftChild!)
                    queue.append(node.rightChild!)
                }
            }
        }
    }
}

이 코드는 TreeNode 클래스와 BinaryTree 클래스를 사용하여 이진 트리를 구현합니다. 값을 삽입할 때는 너비 우선 탐색(BFS)을 사용하여 트리의 적절한 위치에 노드를 추가합니다. 이와 같이 제네릭을 활용하면 다양한 데이터 타입에 대응할 수 있는 트리 구조를 설계할 수 있습니다.

제네릭을 활용한 커스텀 데이터 구조의 장점

제네릭을 사용하면 데이터 구조의 유연성과 재사용성이 증가합니다. 동일한 코드 베이스로 다양한 타입의 데이터를 처리할 수 있기 때문에 코드의 가독성과 유지보수성이 향상됩니다. 더불어 데이터 타입에 구애받지 않고 새로운 데이터를 추가하거나 조작하는 로직을 쉽게 구현할 수 있습니다.

요약하자면, Swift의 제네릭 시스템은 강력한 도구로서 다양한 커스텀 데이터 구조를 손쉽게 설계하고 구현할 수 있게 해줍니다. 링크드 리스트, 트리 등 복잡한 데이터 구조를 제네릭과 결합하여 유연하게 다룰 수 있는 방법을 익혀두면 프로그래밍의 많은 부분에서 큰 이점을 얻을 수 있을 것입니다.