Rust中链表的Peek实现

1tuwyuhd  于 2022-12-27  发布在  其他
关注(0)|答案(2)|浏览(156)

https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=693594655ea355b40e2175542c653879
我想用peek()删除列表的最后一个元素,返回data

type Link<T> = Option<Box<Node<T>>>;

struct Node<T> {
    pub data: T,
    pub next: Link<T>,
}

struct List<T> {
    pub head: Link<T>,
}

impl<T> List<T> {
    fn peek(&mut self) -> Option<T> {
        let mut node = &self.head;

        while let Some(cur_node) = &mut node {
            if cur_node.next.is_some() {
                node = &cur_node.next;
                continue;
            }
        }
        let last = node.unwrap();
        let last = last.data;
        return Some(last);
    }
}

#[test]
fn peek_test() {
    let mut q = List::new();
    q.push(1);
    q.push(2);
    q.push(3);

    assert_eq!(q.empty(), false);
    assert_eq!(q.peek().unwrap(), 1);
    assert_eq!(q.peek().unwrap(), 2);
    assert_eq!(q.peek().unwrap(), 3);
    assert_eq!(q.empty(), true);
}

为了保存head,我需要通过引用访问元素,但是这个问题并不适合我,我查看了“too-many-lists”,但是值只是通过引用返回,我想删除tail元素。

kqlmhetl

kqlmhetl1#

要实现这一点,必须从接受共享引用(&)切换到接受可变引用。
这会导致代码中的借用检查器错误,这就是为什么我必须将while let循环更改为检查下一个元素是否为Some的循环,然后才能以可变方式借用节点的内容并推进它。
最后,我Option::take最后一个元素并返回它的数据,我使用Option::map来避免使用unwrap,它会因为空列表而崩溃,如果你想保留你的变量,你应该用try操作符?替换unwrap
简而言之,您可以像这样实现pop_back

pub fn pop_back(&mut self) -> Option<T> {
        let mut node = &mut self.head;
        while node.as_ref().map(|n| n.next.is_some()).unwrap_or_default() {
            node = &mut node.as_mut().unwrap().next;
        }
        node.take().map(|last| last.data)
    }
wtzytmuj

wtzytmuj2#

我建议像下面这样的东西,只是因为我花了时间在上面。-)

fn peek(&mut self) -> Option<T> {
        
        match &self.head { 
            None => return None,
            Some(v) => 
                if v.next.is_none() {
                    let last = self.head.take();
                    let last = last.unwrap().data;
                    return Some(last);
                }
        }
        
        let mut current = &mut self.head;
        loop {
            match current {
                None => return None,
                Some(node) if node.next.is_some() && match &node.next { None => false, Some(v) => v.next.is_none()} => {
                    let last = node.next.take();
                    let last = last.unwrap().data;
                    return Some(last);
                },
                Some(node) => {
                    current = &mut node.next;
                }
            }
        }
       
    }

相关问题