【Rust】枚举类型创建单链表以及常见的链表操作方法

目录

单链表

用枚举表达链表

枚举enum

Box容器

创建节点

[1. 创建并打印](#1. 创建并打印)

[2. match 匹配](#2. match 匹配)

[3. 节点初始化](#3. 节点初始化)

4.节点嵌套

追加节点

[1. 尾插法](#1. 尾插法)

[2. 链表追加方法](#2. 链表追加方法)

[3. 头插法](#3. 头插法)

[4. 改写成单链表方法](#4. 改写成单链表方法)

遍历链表

[1. 递归法](#1. 递归法)

[2. 递推法](#2. 递推法)

[3. 改写成单链表方法](#3. 改写成单链表方法)

[自定义Display trait](#自定义Display trait)

创建链表

[1. 递归法](#1. 递归法)

[2. 递推法](#2. 递推法)

[3. 改写成单链表方法](#3. 改写成单链表方法)

链表长度

翻转链表

[1. 递归法](#1. 递归法)

[2. 递推法](#2. 递推法)

[3. 改写成单链表关联函数和方法](#3. 改写成单链表关联函数和方法)

删除尾节点

汇总小结

相关方法

自定义trait

完整代码

真题实战

[合并两个有序链表 Mmerge-two-sorted-lists](#合并两个有序链表 Mmerge-two-sorted-lists)


单链表

单链表(Linked List)是一种线性数据结构,由一系列节点组成,每个节点包含一个数据元素和一个指向下一个节点的指针。单链表的特点是每个节点只能指向一个下一个节点,没有指向上一个节点的指针。

单链表的基本操作包括插入、删除、查找等。插入操作需要在指定位置插入一个新节点,删除操作需要删除指定位置的节点,查找操作需要找到指定值的节点位置。

单链表的优势是插入和删除操作相对简单,不需要移动大量元素,时间复杂度为O(1)。但单链表在查找操作上的时间复杂度是O(n),因为需要从头节点开始逐个比较直到找到目标节点。

用枚举表达链表

rust 复制代码
enum List {
    None,
    Node(i32, Box<List>),
}

枚举成员: List::None 、 List::Node(i32, Box<List>)

枚举enum

Rust 是一种编程语言,支持多种类型的的数据,其中之一就是枚举类型(Enum)。枚举类型是一种特殊的数据类型,它定义了一组可能的值。每个值都有一个特定的类型,并且可以用来表示不同的含义。

Rust 中的枚举类型通常使用关键字 enum 来定义,后接名称;枚举有多个成员(variant),每个成员是该 enum 类型的一个可能值。

例如,定义一个表示颜色类型的的枚举:

enum Color { Red, Green, Blue, }

这个 Color 类型有三种可能的值:RedGreenBlue,使用这些值来存储不同颜色的值。

枚举类型的一个重要作用是使得代码更具可读性和可维护性。例如,如果使用一个 String 类型的颜色值,必须要确保该字符串始终有效,否则程序可能会崩溃。而使用枚举类型,可以明确指定可能的值,从而减少了此类错误的发生。

另外,Rust 还支持模式匹配,可以方便地检查一个枚举类型的值是哪个模式,这使得代码更加简洁和可读。例如:

rust 复制代码
let c = Color::Red;  
match c {  
    Color::Red => println!("It's red!"),  
    Color::Green => println!("It's green!"),  
    Color::Blue => println!("It's blue!"),  
};

在这个例子中,使用 match 表达式来检查 c 的值是哪个模式。根据不同的模式,可以执行不同的代码。

Box容器

Rust中的Box是一种通用容器,可以存储任意类型的数据。它类似于C++中的unique_ptr,但还提供了一些额外的功能。

通过使用Box,您可以在堆上分配内存,而不需要手动管理内存的分配和释放。这使得使用Box成为一种方便的方式来存储和管理动态分配的内存。

Box还提供了一些优势,例如能够解决递归类型的大小问题。在Rust中,基本类型无法实现递归,但可以使用Box将递归类型的大小固定下来。

以下是一个使用Box的简单示例:

rust 复制代码
use std::boxed::Box;  
  
fn main() {  
    let ibox = Box::new(5);  
    println!("{}", ibox); 
    println!("{}", *ibox);
    println!("{}", ibox.as_ref());
}

这个程序创建了一个Box容器,输出结果为3个5,但有不同的含义:

println!("{}", ibox);

这行代码使用 println! 宏打印一个 Box 对象 ibox 的值。{} 是一个占位符,表示将对象的值插入到此处。在这种情况下,ibox 的值将被打印出来,因为 Box 类型实现了 Display trait,可以将其值转换为字符串形式。

println!("{}", *ibox);

这行代码使用 println! 宏打印 ibox 解引用后的值。在 Rust 中,* 运算符用于解引用指针,即获取指针指向的实际值。在这种情况下,ibox 是一个 Box 对象,存储了一个整数值。通过解引用操作,我们获取到这个整数值并打印出来。

println!("{}", ibox.as_ref());

这行代码使用 println! 宏打印 ibox 的引用。as_ref() 方法返回一个引用,可以用于访问 Box 对象中的数据。在这种情况下,我们将 ibox 转换为引用,并通过引用访问其值并打印出来。

通过使用Box,可以方便地在Rust中管理和访问动态分配的内存,而不需要手动管理内存的分配和释放。

创建节点

1. 创建并打印

创建单个节点,并使用 #[derive(Debug)] 及 println! 打印输出:

rust 复制代码
#[derive(Debug)]
enum List {
    None,
    Node(i32, Box<List>),
}

fn main() {
    let head = List::Node(1, Box::new(List::None));
    println!("{:?}", head);
    let head = List::Node(2, Box::new(List::None));
    println!("{:?}", head);
}

输出:

Node(1, None)

Node(2, None)

2. match 匹配

创建节点,并使用match表达式匹配枚举成员:

rust 复制代码
enum List {
    None,
    Node(i32, Box<List>),
}

fn main() {
    let list1 = List::None;
    let list2 = List::Node(1, Box::new(List::None));

    match list1 {
        List::None => println!("List::None"),
        List::Node(_, _) => println!("List::Node"),
    }

    match list2 {
        List::None => println!("List::None"),
        List::Node(value, _) => println!("List::Node({})", value),
    }
}

输出:

List::None

List::Node(1)

3. 节点初始化

new()初始化函数:fn new(value: i32)

rust 复制代码
#[derive(Debug)]
enum List {
    None,
    Node(i32, Box<List>),
}

impl List {
    fn new(value: i32) -> Self {
        List::Node(value, Box::new(List::None))
    }
}

fn main() {
    let head = List::new(1);
    println!("{:?}", head);
    let head = List::new(2);
    println!("{:?}", head); 
    let head = List::new(3);
    println!("{:?}", head); 
}

输出:

Node(1, None)

Node(2, None)

Node(3, None)

4.节点嵌套

通过嵌套多个节点形成单链表:

rust 复制代码
#[derive(Debug)]
enum List {
    None,
    Node(i32, Box<List>),
}

fn main() {
    let head = List::Node(
        1, Box::new(List::Node(
            2, Box::new(List::Node(
                3, Box::new(List::Node(
                    4, Box::new(List::None),
                )),
            )),
        )),
    );
    println!("{:?}", head);
}

输出:

Node(1, Node(2, Node(3, Node(4, None))))


通过枚举类型表达成一个单链表 ,同样,这种方法甚至还能表达一棵二叉树

rust 复制代码
#[derive(Debug)]
enum Tree {  
    None,  
    Node(i32, Box<Tree>, Box<Tree>),  
} 

fn main() { 
    let tree = Tree::Node(  
        1,  
        Box::new(Tree::Node(2, Box::new(Tree::None), Box::new(Tree::None))),  
        Box::new(Tree::Node(
            3,
            Box::new(Tree::Node(4, Box::new(Tree::None), Box::new(Tree::None))),
            Box::new(Tree::Node(5, Box::new(Tree::None), Box::new(Tree::None))),
            ),
        ),  
    );   
    println!("{:?}", tree);
}

输出:

Node(1, Node(2, None, None), Node(3, Node(4, None, None), Node(5, None, None)))

二叉树相对单链表要复杂,有空再研究;还是继续探究单链表的其它操作吧。


追加节点

1. 尾插法

函数 append() 在链表尾部追加节点:

rust 复制代码
#[derive(Debug)]
enum List {
    None,
    Node(i32, Box<List>),
}

fn append(list: &mut List, value: i32) {
    match list {
        List::None => {
            *list = List::Node(value, Box::new(List::None));
        }
        List::Node(_, next) => {
            append(next, value);
        }
    }
}

fn main() {
    let mut head = List::Node(
        1, Box::new(List::Node(
            2, Box::new(List::Node(
                3, Box::new(List::Node(
                    4, Box::new(List::None),
                )),
            )),
        )),
    );
    println!("{:?}", head);

    append(&mut head, 5);
    println!("{:?}", head);
}

输出:

Node(1, Node(2, Node(3, Node(4, None))))

Node(1, Node(2, Node(3, Node(4, Node(5, None)))))

2. 链表追加方法

把append()函数改造成链表方法:

rust 复制代码
#[derive(Debug)]
enum List {
    None,
    Node(i32, Box<List>),
}

impl List {
    fn new(value: i32) -> Self {
        List::Node(value, Box::new(List::None))
    }

    fn append(self, value: i32) -> Self {
        match self {
            List::None => List::Node(value, Box::new(List::None)),
            List::Node(v, next) => List::Node(v, Box::new(next.append(value))),
        }
    }
}

fn main() {
    let head = List::new(1);
    println!("{:?}", head);

    let head = head.append(2);
    println!("{:?}", head);

    let head = head.append(3);
    println!("{:?}", head);
}

输出:

Node(1, None)

Node(1, Node(2, None))

Node(1, Node(2, Node(3, None)))

3. 头插法

除了尾部追加,也能在头部插入:

rust 复制代码
#[derive(Debug)]
enum List {
    None,
    Node(i32, Box<List>),
}

fn main() {
    let mut head = List::Node(1, Box::new(List::None));
    head = List::Node(2, Box::new(head));
    head = List::Node(3, Box::new(head));
    head = List::Node(4, Box::new(head));
    println!("{:?}", head);
}

输出:

Node(4, Node(3, Node(2, Node(1, None))))

头插法得到一个反序的单链表:

4. 改写成单链表方法

对比append()和.push_back()不同之处:

rust 复制代码
#[derive(Debug)]
enum List {
    None,
    Node(i32, Box<List>),
}

impl List {
    fn new(value: Option<i32>) -> Self {
        match value {
            Some(value) => List::Node(value, Box::new(List::None)),
            None => List::None,
        }
    }

    fn append(self, value: i32) -> Self {
        match self {
            List::None => List::new(Some(value)),
            List::Node(v, next) => List::Node(v, Box::new(next.append(value))),
        }
    }
    
    fn push_back(&mut self, value: i32) {
        match self {
            List::None => {
                *self = List::new(Some(value));
            }
            List::Node(_, next) => {
                next.push_back(value);
            }
        }
    }
}

fn main() {
    let head = List::new(None);
    println!("{:?}", head);
    let head = head.append(1);
    let head = head.append(2);
    println!("{:?}", head);
    println!();

    let mut head = List::new(Some(1));
    println!("{:?}", head);
    for value in 2..5 {
        head.push_back(value);
    }
    println!("{:?}", head);
}

输出:

None

Node(1, Node(2, None))

Node(1, None)

Node(1, Node(2, Node(3, Node(4, None))))

push_back()推荐使用递归法,代码比较精炼;递推迭代法如下:

rust 复制代码
    fn push_back(&mut self, value: i32) {
        match self {
            List::None => {
                *self = List::new(Some(value));
            }
            List::Node(_, next) => {
                if let List::None = &**next {
                    *next = Box::new(List::new(Some(value)));
                } else {
                    let mut curr = next;
                    while let List::Node(_, ref mut next) = **curr {
                        curr = next;
                    }
                    *curr = Box::new(List::new(Some(value)));
                }
            }
        }
    }

遍历链表

1. 递归法

rust 复制代码
#[derive(Debug)]
enum List {
    None,
    Node(i32, Box<List>),
}

fn traverse(list: &List) {
    match list {
        List::None => println!("nil"),
        List::Node(value, next) => {
            print!("{}->", value);
            traverse(next);
        }
    }
}

fn main() {
    let head = List::Node(
        1,
        Box::new(List::Node(
            2,
            Box::new(List::Node(
                3,
                Box::new(List::None),
            )),
        )),
    );

    println!("{:?}", head);
    traverse(&head);
}

输出:

Node(1, Node(2, Node(3, None)))

1->2->3->nil

2. 递推法

rust 复制代码
#[derive(Debug)]
enum List {
    None,
    Node(i32, Box<List>),
}

fn traverse(head: &List) {
    let mut cur = head;
    while let List::Node(value, next) = cur {
        print!("{}->", value);
        cur = next;
    }
    println!("nil");
}

fn main() {
    let head = List::Node(
        1,
        Box::new(List::Node(
            2,
            Box::new(List::Node(
                3,
                Box::new(List::None),
            )),
        )),
    );

    println!("{:?}", head);
    traverse(&head);
}

输出:

Node(1, Node(2, Node(3, None)))

1->2->3->nil

while let 语句比较简洁,相当于loop+if let:

rust 复制代码
fn traverse(head: &List) {
    let mut cur = head;
    loop {
        if let List::Node(value, next) = cur {
            print!("{}->", value);
            cur = next;
        } else {
            println!("nil");
            break;
        }
    }
}

使用 loop+match 也能遍历:

rust 复制代码
fn traverse(head: &List) {
    let mut cur = head;
    loop {
        match cur {
            List::None => {
                println!("nil");
                break;
            }
            List::Node(value, next) => {
                print!("{}->", value);
                cur = next;
            }
        }
    }
}

3. 改写成单链表方法

rust 复制代码
enum List {
    None,
    Node(i32, Box<List>),
}

impl List {
    fn traverse(&self) {
        let mut curr = self;
        while let List::Node(value, next) = curr {
            print!("{}->", value);
            curr = next;
        }
        println!("nil");
    }
}

fn main() {
    let head = List::Node(
        1, Box::new(List::Node(
            2, Box::new(List::Node(
                3, Box::new(List::None),
            )),
        )),
    );
    head.traverse();
}

输出:

1->2->3->nil


自定义Display trait

为与遍历函数区分,在trait输出时用"Nil"标记

rust 复制代码
use std::fmt;

#[derive(Debug)]
enum List {
    None,
    Node(i32, Box<List>),
}

impl fmt::Display for List {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            List::None => write!(f, "Nil"),
            List::Node(value, next) => {
                write!(f, "{}->", value)?;
                write!(f, "{}", *next)?;
                Ok(())
            }
        }
    }
}

fn traverse(head: &List) {
    let mut cur = head;
    while let List::Node(value, next) = cur {
        print!("{}->", value);
        cur = next;
    }
    println!("nil");
}

fn main() {  
    let head = List::Node(
        1, Box::new(List::Node(
            2, Box::new(List::Node(
                3, Box::new(List::None),
            )),
        )),
    );
  
    println!("{}", head);
    traverse(&head);
}

输出:

1->2->3->Nil

1->2->3->nil


创建链表

直接把动态数组Vec创建成单链表。

1. 递归法

rust 复制代码
#[derive(Debug)]
enum List {
    None,
    Node(i32, Box<List>),
}

fn traverse(head: &List) {
    let mut cur = head;
    while let List::Node(value, next) = cur {
        print!("{}->", value);
        cur = next;
    }
    println!("nil");
}

fn create(values: Vec<i32>) -> List {
    fn _helper(values: &Vec<i32>, index: usize) -> List {
        if index < values.len() {
            let value = values[index];
            let next = Box::new(_helper(values, index + 1));
            List::Node(value, next)
        } else {
            List::None
        }
    }
    _helper(&values, 0)
}

fn main() {
    let values = vec![1, 2, 3, 4, 5];
    let head = create(values.clone());
    println!("{:?}", head);
    traverse(&head);
}

输出:

Node(1, Node(2, Node(3, Node(4, Node(5, None)))))

1->2->3->4->5->nil

2. 递推法

rust 复制代码
#[derive(Debug)]
enum List {
    None,
    Node(i32, Box<List>),
}

fn traverse(head: &List) {
    let mut cur = head;
    while let List::Node(value, next) = cur {
        print!("{}->", value);
        cur = next;
    }
    println!("nil");
}

fn create(values: Vec<i32>) -> List {
    let mut list = List::None;
    for &value in values.iter().rev() {
        list = List::Node(value, Box::new(list));
    }
    list
}

fn main() {
    let values = vec![1, 2, 3, 4, 5];
    let head = create(values.clone());
    println!("{:?}", head);
    traverse(&head);
}

输出:

Node(1, Node(2, Node(3, Node(4, Node(5, None)))))

1->2->3->4->5->nil

3. 改写成单链表方法

rust 复制代码
enum List {
    None,
    Node(i32, Box<List>),
}

impl List {
    fn traverse(&self) {
        let mut curr = self;
        while let List::Node(value, next) = curr {
            print!("{}->", value);
            curr = next;
        }
        println!("nil");
    }

    fn create(values: Vec<i32>) -> List {
        let mut list = List::None;
        for &value in values.iter().rev() {
            list = List::Node(value, Box::new(list));
        }
        list
    }
}

fn main() {
    let head = List::create(vec!(1,2,3,4,5));
    head.traverse();
}

输出:

1->2->3->4->5->nil


链表长度

遍历链表时改打印为计数即可:

rust 复制代码
enum List {
    None,
    Node(i32, Box<List>),
}

impl List {
    fn create(values: Vec<i32>) -> List {
        let mut list = List::None;
        for &value in values.iter().rev() {
            list = List::Node(value, Box::new(list));
        }
        list
    }

    fn traverse(&self) {
        let mut curr = self;
        while let List::Node(value, next) = curr {
            print!("{}->", value);
            curr = next;
        }
        println!("nil");
    }

    fn get_size(&self) -> usize {
        let mut length = 0;
        let mut curr = self;
        while let List::Node(_, next) = curr {
            length += 1;
            curr = next;
        }
        length
    }
}

fn main() {
    let head = List::create(vec![1, 2, 3]);
    head.traverse();
    let length = head.get_size();
    println!("Length of list: {}", length);

    let head = List::create(vec![1, 2, 3, 4, 5]);
    head.traverse();
    let length = head.get_size();
    println!("Length of list: {}", length);
}

输出:

1->2->3->nil

Length of list: 3

1->2->3->4->5->nil

Length of list: 5


翻转链表

把单链表翻转,即头尾反向。

1. 递归法

rust 复制代码
#[derive(Debug)]
enum List {
    None,
    Node(i32, Box<List>),
}

fn traverse(head: &List) {
    let mut cur = head;
    while let List::Node(value, next) = cur {
        print!("{}->", value);
        cur = next;
    }
    println!("nil");
}

fn create(values: Vec<i32>) -> List {
    let mut list = List::None;
    for &value in values.iter().rev() {
        list = List::Node(value, Box::new(list));
    }
    list
}

fn reversed(list: &List) -> List {
    fn _helper(list: &List, prev: List) -> List {
        match list {
            List::None => prev,
            List::Node(value, next) => {
                _helper(next, List::Node(*value, Box::new(prev)))
            },
        }
    }
    _helper(list, List::None)
}

fn main() {
    let values = vec![1, 2, 3, 4, 5];
    let head = create(values);
    traverse(&head);
    let head = reversed(&head);
    traverse(&head);
}

输出:

1->2->3->4->5->nil

5->4->3->2->1->nil

2. 递推法

rust 复制代码
enum List {
    None,
    Node(i32, Box<List>),
}

fn traverse(head: &List) {
    let mut curr = head;
    while let List::Node(value, next) = curr {
        print!("{}->", value);
        curr = next;
    }
    println!("nil");
}

fn create(values: Vec<i32>) -> List {
    let mut list = List::None;
    for &value in values.iter().rev() {
        list = List::Node(value, Box::new(list));
    }
    list
}

fn reversed(head: &List) -> List {
    let mut list = List::None;
    let mut curr = head;
    while let List::Node(value, next) = curr {
        list = List::Node(*value, Box::new(list));
        curr = next;
    }
    list
}

fn main() {
    let values = vec![1, 2, 3, 4, 5];
    let head = create(values);
    traverse(&head);
    let head = reversed(&head);
    traverse(&head);
}

输出:

1->2->3->4->5->nil

5->4->3->2->1->nil

3. 改写成单链表关联函数和方法

对比关联函数reversed()和方法.reverse()不同之处:

rust 复制代码
enum List {
    None,
    Node(i32, Box<List>),
}

impl List {
    fn new(value: Option<i32>) -> Self {
        match value {
            Some(value) => List::Node(value, Box::new(List::None)),
            None => List::None,
        }
    }

    fn traverse(&self) {
        let mut curr = self;
        while let List::Node(value, next) = curr {
            print!("{}->", value);
            curr = next;
        }
        println!("nil");
    }

    fn create(values: Vec<i32>) -> List {
        let mut list = List::None;
        for &value in values.iter().rev() {
            list = List::Node(value, Box::new(list));
        }
        list
    }

    fn reversed(&self) -> Self {
        let mut list = List::new(None);
        let mut curr = self;
        while let List::Node(value, next) = curr {
            list = List::Node(*value, Box::new(list));
            curr = next;
        }
        list
    }

    fn reverse(&mut self) {
        let mut tail = List::new(None);
        let mut curr = std::mem::replace(self, List::None);
        while let List::Node(value, next) = std::mem::replace(&mut curr, List::None) {
            let node = List::Node(value, Box::new(tail));
            (tail, curr) = (node, *next);
        }
        std::mem::swap(self, &mut tail);
    }
}

fn main() {
    let values = vec![1, 2, 3, 4, 5];
    let mut head = List::create(values);
    head.traverse();
    head.reverse();
    head.traverse();
    head = List::reversed(&head);
    head.traverse();
}

输出:

1->2->3->4->5->nil

5->4->3->2->1->nil

1->2->3->4->5->nil


删除尾节点

删除链表尾节点pop(),并返回尾节点的值

rust 复制代码
#![allow(dead_code)]

enum List {
    None,
    Node(i32, Box<List>),
}

impl List {
    fn new(value: Option<i32>) -> Self {
        match value {
            Some(value) => List::Node(value, Box::new(List::None)),
            None => List::None,
        }
    }

    fn create(values: Vec<i32>) -> List {
        let mut list = List::None;
        for &value in values.iter().rev() {
            list = List::Node(value, Box::new(list));
        }
        list
    }

    fn traverse(&self) {
        let mut curr = self;
        while let List::Node(value, next) = curr {
            print!("{}->", value);
            curr = next;
        }
        println!("nil");
    }

    fn pop(&mut self) -> Option<i32> {
        match self {
            List::None => None,
            List::Node(value, next) => {
                if let List::None = **next {
                    let popped_value = *value;
                    *self = List::None;
                    Some(popped_value)
                } else {
                    next.pop()
                }
            }
        }
    }
}

fn main() {
    let values = vec![1, 2, 3, 4, 5];
    let mut head = List::create(values);
    head.traverse();
    for _ in 1..=6 {
        if let Some(value) = head.pop() {
            println!("Popped value: {}", value);
        } else {
            println!("List is empty");
        }
        head.traverse();
    }
}

输出:

1->2->3->4->5->nil

Popped value: 5

1->2->3->4->nil

Popped value: 4

1->2->3->nil

Popped value: 3

1->2->nil

Popped value: 2

1->nil

Popped value: 1

nil

List is empty

nil


汇总小结

List 枚举定义了链表的两种可能状态:None 和 Node。

其中,Node 表示链表节点,包含一个整数值和一个指向下一个节点的 Box<List>。

相关方法

相关的方法或关联函数,归纳如下:

new:创建一个新的链表节点或空链表。

append:在链表尾部添加一个节点,并返回添加后的链表。

push_back:在链表尾部添加一个节点,将链表修改为添加后的结果。

create:根据给定的数组构建一个链表。

reversed:反转链表,返回一个反转后的链表。

reverse:反转链表,将链表修改为反转后的结果。

traverse:遍历并打印链表中的节点值。

get_size:遍历出链表的节点数,返回链表长度。

pop:删除链表尾节点,并返回尾节点的值。

自定义trait

自定义trait Display,使链表的输出不依赖trait Debug:

```Rust

impl std::fmt::Display for List {

fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {

match self {

List::None => write!(f, "nil"),

List::Node(value, next) => {

write!(f, "{}->", value)?;

write!(f, "{}", *next)?;

write!(f, "")

}

}

}

}

```

完整代码

InsCode - 让你的灵感立刻落地

https://inscode.csdn.net/@boysoft2002/RustEnumList

rust 复制代码
#![allow(dead_code)]

enum List {
    None,
    Node(i32, Box<List>),
}

impl std::fmt::Display for List {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        match self {
            List::None => write!(f, "nil"),
            List::Node(value, next) => {
                write!(f, "{}->", value)?;
                write!(f, "{}", *next)?;
                Ok(())
            }
        }
    }
}

impl List {
    fn new(value: Option<i32>) -> Self {
        match value {
            Some(value) => List::Node(value, Box::new(List::None)),
            None => List::None,
        }
    }

    fn append(self, value: i32) -> Self {
        match self {
            List::None => List::new(Some(value)),
            List::Node(v, next) => List::Node(v, Box::new(next.append(value))),
        }
    }

    fn push_back(&mut self, value: i32) {
        match self {
            List::None => {
                *self = List::new(Some(value));
            }
            List::Node(_, next) => {
                next.push_back(value);
            }
        }
    }

    fn create(values: Vec<i32>) -> Self {
        let mut list = List::new(None);
        for &value in values.iter().rev() {
            list = List::Node(value, Box::new(list));
        }
        list
    }

    fn get_size(&self) -> usize {
        let mut length = 0;
        let mut curr = self;
        while let List::Node(_, next) = curr {
            length += 1;
            curr = next;
        }
        length
    }

    fn reversed(&self) -> Self {
        let mut list = List::new(None);
        let mut curr = self;
        while let List::Node(value, next) = curr {
            list = List::Node(*value, Box::new(list));
            curr = next;
        }
        list
    }

    fn reverse(&mut self) {
        let mut tail = List::new(None);
        let mut curr = std::mem::replace(self, List::None);
        while let List::Node(value, next) = std::mem::replace(&mut curr, List::None) {
            let node = List::Node(value, Box::new(tail));
            (tail, curr) = (node, *next);
        }
        std::mem::swap(self, &mut tail);
    }

    fn pop(&mut self) -> Option<i32> {
        match self {
            List::None => None,
            List::Node(value, next) => {
                if let List::None = **next {
                    let popped_value = *value;
                    *self = List::None;
                    Some(popped_value)
                } else {
                    next.pop()
                }
            }
        }
    }

    fn traverse(self: &Self) {
        let mut curr = self;
        while let List::Node(value, next) = curr {
            print!("{}->", value);
            curr = next;
        }
        println!("nil");
    }
}  

fn main() {  
    let head = List::new(None);
    head.traverse();
    let head = head.append(1);
    let head = head.append(2);
    head.traverse();
    println!();

    let mut head = List::new(Some(1));
    head.traverse();
    for value in 2..5 {
        head.push_back(value);
    }
    head.traverse();
    println!();

    let values = vec![1, 2, 3, 4, 5];
    head = List::create(values);
    head.traverse();
    head = head.reversed();
    println!("{}", head);
    head.reverse();
    println!("{}", head);
    let length = head.get_size();
    println!("Length of list: {}", length);
    println!();

    if let Some(value) = head.pop() {
        println!("Popped value: {}", value);
    } else {
        println!("List is empty");
    }
    head.traverse();
    println!("Length of list: {}", head.get_size());
}

输出:

nil

1->2->nil

1->nil

1->2->3->4->nil

1->2->3->4->5->nil

5->4->3->2->1->nil

1->2->3->4->5->nil

Length of list: 5

Popped value: 5

1->2->3->4->nil

Length of list: 4


真题实战

合并两个有序链表 Mmerge-two-sorted-lists

将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。

示例 1:

输入:l1 = [1,2,4], l2 = [1,3,4]

输出:[1,1,2,3,4,4]

示例 2:

输入:l1 = [], l2 = []

输出:[]

示例 3:

输入:l1 = [], l2 = [0]

输出:[0]

提示:

两个链表的节点数目范围是 [0, 50]

-100 <= Node.val <= 100

l1 和 l2 均按 非递减顺序 排列

代码:

rust 复制代码
#[derive(Clone)]
enum List {
    None,
    Node(i32, Box<List>),
}

fn create(values: Vec<i32>) -> List {
    let mut list = List::None;
    for &value in values.iter().rev() {
        list = List::Node(value, Box::new(list));
    }
    list
}

fn traverse(head: &List) {
    let mut cur = head;
    while let List::Node(value, next) = cur {
        print!("{}->", value);
        cur = next;
    }
    println!("nil");
}

fn merge_lists(l1: List, l2: List) -> List {
    match (l1.clone(), l2.clone()) {
        (List::None, _) => l2,
        (_, List::None) => l1,
        (List::Node(x, box1), List::Node(y, box2)) => {
            if x < y {
                List::Node(x, Box::new(merge_lists(*box1, l2)))
            } else {
                List::Node(y, Box::new(merge_lists(l1, *box2)))
            }
        }
    }
}

fn main() {
    let nums1 = vec![1, 2, 4];
    let nums2 = vec![1, 2, 3];
    let list1 = create(nums1);
    let list2 = create(nums2);
    traverse(&list1);
    traverse(&list2);
    let merged = merge_lists(list1, list2);
    traverse(&merged);
}

输出:

1->2->4->nil

1->2->3->nil

1->1->2->2->3->4->nil

相关推荐
代码小鑫6 分钟前
A031-基于SpringBoot的健身房管理系统设计与实现
java·开发语言·数据库·spring boot·后端
Json____11 分钟前
学法减分交管12123模拟练习小程序源码前端和后端和搭建教程
前端·后端·学习·小程序·uni-app·学法减分·驾考题库
monkey_meng31 分钟前
【Rust类型驱动开发 Type Driven Development】
开发语言·后端·rust
落落落sss39 分钟前
MQ集群
java·服务器·开发语言·后端·elasticsearch·adb·ruby
大鲤余1 小时前
Rust,删除cargo安装的可执行文件
开发语言·后端·rust
Source.Liu1 小时前
不安全 Rust
安全·rust
她说彩礼65万1 小时前
Asp.NET Core Mvc中一个视图怎么设置多个强数据类型
后端·asp.net·mvc
陈随易1 小时前
农村程序员-关于小孩教育的思考
前端·后端·程序员
_江南一点雨1 小时前
SpringBoot 3.3.5 试用CRaC,启动速度提升3到10倍
java·spring boot·后端
转转技术团队2 小时前
空间换时间-将查询数据性能提升100倍的计数系统实践
java·后端·架构