Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

테스트케이스: 연결 리스트

연결 리스트를 구현하는 일반적인 방법은 enums를 사용하는 것입니다:

use crate::List::*;

enum List {
    // Cons: 요소와 다음 노드에 대한 포인터를 감싸는 튜플 구조체
    Cons(u32, Box<List>),
    // Nil: 연결 리스트의 끝을 나타내는 노드
    Nil,
}

// 열거형에 메서드를 붙일 수 있습니다
impl List {
    // 빈 리스트를 생성합니다
    fn new() -> List {
        // `Nil`은 `List` 타입을 가집니다
        Nil
    }

    // 리스트를 소비하고, 그 앞에 새로운 요소가 추가된 동일한 리스트를 반환합니다
    fn prepend(self, elem: u32) -> List {
        // `Cons` 역시 `List` 타입을 가집니다
        Cons(elem, Box::new(self))
    }

    // 리스트의 길이를 반환합니다
    fn len(&self) -> u32 {
        // 메서드의 동작이 `self`의 변체에 따라 달라지므로 `self`에 대해 매치(match)를 수행해야 합니다.
        // `self`는 `&List` 타입이고, `*self`는 `List` 타입입니다. 구체적인 타입 `T`에 대한 매칭이
        // 참조 `&T`에 대한 매칭보다 선호됩니다.
        // Rust 2018 이후에는 여기서 self를 사용하고 아래에서 tail(ref 없이)을 사용할 수도 있습니다.
        // Rust가 &s와 ref tail을 추론할 것입니다.
        // 참고: https://doc.rust-lang.org/edition-guide/rust-2018/ownership-and-lifetimes/default-match-bindings.html
        match *self {
            // `self`가 빌려온 상태이므로 꼬리(tail)의 소유권을 가질 수 없습니다.
            // 대신 꼬리에 대한 참조를 가져옵니다.
            // 그리고 이것은 꼬리 재귀가 아닌 호출이므로 긴 리스트의 경우 스택 오버플로우가 발생할 수 있습니다.
            Cons(_, ref tail) => 1 + tail.len(),
            // 기저 사례(Base Case): 빈 리스트의 길이는 0입니다
            Nil => 0
        }
    }

    // 리스트를 (힙에 할당된) 문자열 표현으로 반환합니다
    fn stringify(&self) -> String {
        match *self {
            Cons(head, ref tail) => {
                // `format!`은 `print!`와 유사하지만, 콘솔에 출력하는 대신
                // 힙에 할당된 문자열을 반환합니다
                format!("{}, {}", head, tail.stringify())
            },
            Nil => {
                format!("Nil")
            },
        }
    }
}

fn main() {
    // 빈 연결 리스트를 생성합니다
    let mut list = List::new();

    // 몇 가지 요소를 앞에 추가합니다
    list = list.prepend(1);
    list = list.prepend(2);
    list = list.prepend(3);

    // 리스트의 최종 상태를 보여줍니다
    println!("연결 리스트의 길이는 {}입니다", list.len());
    println!("{}", list.stringify());
}

참고:

Box메서드