一个较为完整的rust双链表

ustclyang 2022-04-08 22:55:31

定义节点枚举

pub enum Node<T> {
    Cons(T, Rc<RefCell<Node<T>>>, Rc<RefCell<Node<T>>>),
    Nil,
}

定义迭代器

    //右迭代器
    pub mod iter_r {
        use std::{rc::Rc, cell::RefCell};
        use super::Node::{*, self};
        pub struct IterR<T> {
            cur: Rc<RefCell<Node<T>>>
        }

        impl<T> IterR<T> {
            pub fn new(cur: Rc<RefCell<Node<T>>>) -> IterR<T> {
                IterR { cur }
            }
        }

        impl<T> Iterator for IterR<T> {
            type Item = Rc<RefCell<Node<T>>>;

            fn next(&mut self) -> Option<Self::Item> {
                let self_clone = self.cur.clone();
                let tmp = &*self_clone.borrow();
                match tmp {
                    Cons(_, _, r) => {
                        let ret = Some(self.cur.clone());
                        self.cur = r.clone();
                        ret
                    }
                    Nil => {
                        None
                    }
                }
            }
        }
    }

左迭代器同理,不再赘述,详见代码链接

定义链表结构体

    pub struct List<T> {
        head: Rc<RefCell<Node<T>>>,
        tail: Rc<RefCell<Node<T>>>,
        size: u32,
    }

定义链表接口

  • 新建空链表
        //创建新链表
        pub fn new() -> List<T> {
            List {
                head: Rc::new(RefCell::new(Nil)), 
                tail: Rc::new(RefCell::new(Nil)), 
                size: 0 
            }
        }
  • 从vector新建链表
        //从vector创建新链表
        pub fn from(vec: Vec<T>) -> List<T> {
            let mut list = List::new();
            for e in vec {
                list.push_back(e);
            }
            list
        }
  • 返回链表大小
        //返回链表大小
        pub fn size(&self) -> u32 {
            self.size
        }
  • 返回迭代器
        //返回右迭代器
        pub fn iter_r(&self) -> IterR<T> {
            IterR::new(self.head.clone())
        }

        //返回左迭代器
        pub fn iter_l(&self) -> IterL<T> {
            IterL::new(self.tail.clone())
        }
  • 遍历链表
        //向右遍历链表
        pub fn traverse_r(&self) 
        where T: Display {
            for e in self.iter_r() {
                //let tmp = e.borrow();
                if let Cons(val, _, _) = &*e.borrow() { 
                    print!("{} ", val);
                }
            }
            println!();
        }

        //向左遍历链表
        pub fn traverse_l(&self) 
        where T: Display {
            for e in self.iter_l() {
                //let tmp = e.borrow();
                if let Cons(val, _, _) = &*e.borrow() { 
                    print!("{} ", val);
                }
            }
            println!();
        }
  • 尾插
        //尾插
        pub fn push_back(&mut self, val: T) {
            let nil = Rc::new(RefCell::new(Nil));
            let new_node = Rc::new(RefCell::new(Cons(val, self.tail.clone(), nil)));
            let tail_clone = self.tail.clone();
            let tmp = &mut *tail_clone.borrow_mut();
            match tmp {
                Cons(_, _, r) => {
                    *r = new_node.clone();
                    self.tail = new_node.clone();
                    self.size += 1;
                }
                Nil => {
                    self.head = new_node.clone();
                    self.tail = new_node.clone();
                    self.size = 1;
                }
            }
        }
  • 头插
        //头插
        pub fn push_front(&mut self, val: T) {
            let nil = Rc::new(RefCell::new(Nil));
            let new_node = Rc::new(RefCell::new(Cons(val, nil, self.head.clone())));
            let head_clone = self.head.clone();
            let tmp = &mut *head_clone.borrow_mut();
            match tmp {
                Cons(_, l, _) => {
                    *l = new_node.clone();
                    self.head = new_node.clone();
                    self.size += 1;
                }
                Nil => {
                    self.head = new_node.clone();
                    self.tail = new_node.clone();
                    self.size = 1;
                }
            }
        }
  • 中间位置相对插入
        //当前节点之前插入一个节点
        pub fn insert_l(&mut self, cur: Rc<RefCell<Node<T>>>, val: T) {
            let mut borrow = cur.borrow_mut();
            let tmp = &mut *borrow;
            match tmp {
                Nil => panic!("当前节点无效(cur is a nil node)."),
                Cons(_, l, _) => {
                    if Rc::ptr_eq(&cur, &self.head) {
                        //println!("yes");
                        drop(borrow);  //释放RefCell借用
                        self.push_front(val);
                    } else {
                        let lnode = l.clone();
                        let new_node = Rc::new(RefCell::new(Cons(val, lnode.clone(), cur.clone())));
                        let tmp = &mut *lnode.borrow_mut();
                        if let Cons(_, _, r) = tmp {
                            *r = new_node.clone();
                        }
                        //let tmp = &mut *cur.borrow_mut();
                        //if let Cons(_, l, _) = tmp {
                            *l = new_node.clone();
                        //}
                        self.size += 1;
                    }
                }
            }
        }

在当前节点之后插入详见代码链接

  • 查找
        //从左向右查找key第一次出现的节点
        pub fn find_r(&self, key: &T) -> Rc<RefCell<Node<T>>> 
        where T: Ord {
            //todo!()
            for e in self.iter_r() {
                if let Cons(m_key, _, _) = &*e.borrow() {
                    if let Ordering::Equal = key.cmp(m_key) {
                        return e.clone();
                    }
                }
            }
            Rc::new(RefCell::new(Nil))
        }

从右往左查找详见代码链接

  • 删除尾节点
        //删除尾节点
        pub fn pop_back(&mut self) {
            //let nil = Rc::new(RefCell::new(Nil));
            let tail_clone = self.tail.clone();
            let tmp = &mut *tail_clone.borrow_mut();
            match tmp {
                Cons(_, l, _) => {
                    let lnode = &mut *l.borrow_mut();
                    match lnode {
                        Cons(_, _, r) => {
                            *r = Rc::new(RefCell::new(Nil));
                        }
                        Nil => {
                            self.head = Rc::new(RefCell::new(Nil));
                            //self.tail = Rc::new(RefCell::new(Nil));
                            //self.size = 0;
                        }
                    }
                    self.tail = l.clone();
                    self.size -= 1;
                }
                Nil => {
                    panic!("empty link, can't pop a node");
                }
            }
        }

删除头节点详见代码链接

  • 删除当前节点
        //删除当前节点
        pub fn remove(&mut self, cur: Rc<RefCell<Node<T>>>) {
            let mut borrow = cur.borrow_mut();
            let tmp = &mut *borrow;
            match tmp {
                Nil => panic!("当前节点无效(cur is a nil node)."),
                Cons(_, l, r) => {
                    if Rc::ptr_eq(&cur, &self.tail) {
                        //println!("yes");
                        drop(borrow);  //释放RefCell借用
                        self.pop_back();
                    } else if Rc::ptr_eq(&cur, &self.head) {
                        drop(borrow);
                        self.pop_front();
                    } else {
                        let rnode = r.clone();
                        let lnode = l.clone();
                        //let new_node = Rc::new(RefCell::new(Cons(val, cur.clone(), r.clone())));
                        let tmp = &mut *rnode.borrow_mut();
                        if let Cons(_, ll, _) = tmp {
                            *ll = lnode.clone();
                        }

                        let tmp = &mut *lnode.borrow_mut();
                        if let Cons(_, _, rr) = tmp {
                            *rr = rnode.clone();
                        }

                        self.size -= 1;
                    }
                }
            }
        }
  • 修改当前节点
        //修改当前节点
        pub fn modify(&mut self, cur: Rc<RefCell<Node<T>>>, val: T) {
            let mut borrow = cur.borrow_mut();
            let tmp = &mut *borrow;
            match tmp {
                Nil => panic!("当前节点无效(cur is a nil node)."),
                Cons(v, _, _) => {
                    *v = val;
                }
            }
        }

存在的问题

bug:

迭代器不应该以所有权形式返回,应该以一个引用的方式,否则用户可以通过迭代器改变某个节点,

甚至插入删除一个节点,这还不会将链表的size、head、tail同时进行改变,产生严重后果。

(由于我对生命周期理解较浅,本文直接返回所有权)

 注意:

增删改必须提供链表内的节点,随意传入一个节点会出错。用户不应该通过迭代器擅自修改链表,

而应该通过链表提供的接口来完成所需操作,这样的话该链表就是安全的。

 

代码链接

作者:李阳

学号:282

...全文
200 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

571

社区成员

发帖
与我相关
我的任务
社区描述
软件工程教学新范式,强化专项技能训练+基于项目的学习PBL。Git仓库:https://gitee.com/mengning997/se
软件工程 高校
社区管理员
  • 码农孟宁
加入社区
  • 近7日
  • 近30日
  • 至今

试试用AI创作助手写篇文章吧