use std::rc::{Rc, Weak};
use std::cell::RefCell;
#[derive(Debug)]
struct Node {
val: i32,
next: Option<Rc<RefCell<Node>>>,
prev: Option<Weak<RefCell<Node>>>,
}
impl Node {
fn new(val: i32) -> Rc<RefCell<Node>> {
Rc::new(RefCell::new(Node { val, next: None, prev: None }))
}
}
struct DoublyLinkedList {
head: Option<Rc<RefCell<Node>>>,
tail: Option<Rc<RefCell<Node>>>,
}
impl DoublyLinkedList {
fn new() -> Self {
DoublyLinkedList { head: None, tail: None }
}
fn append(&mut self, val: i32) {
let new_node = Node::new(val);
match self.tail.take() {
Some(old_tail) => {
old_tail.borrow_mut().next = Some(new_node.clone());
new_node.borrow_mut().prev = Some(Rc::downgrade(&old_tail));
self.tail = Some(new_node);
}
None => {
self.head = Some(new_node.clone());
self.tail = Some(new_node);
}
}
}
fn delete_from_end(&mut self) {
match self.tail.take() {
None => return, // empty list, nothing to delete
Some(old_tail) => {
let prev = old_tail.borrow_mut().prev.take();
match prev {
Some(weak_prev) => {
if let Some(prev_rc) = weak_prev.upgrade() {
prev_rc.borrow_mut().next = None; // unlink last node
self.tail = Some(prev_rc); // update tail
}
}
None => {
// only one node in list
self.head = None;
self.tail = None;
}
}
}
}
}
fn print_list(&self) {
let mut curr = self.head.clone();
while let Some(node) = curr {
print!("{}", node.borrow().val);
curr = node.borrow().next.clone();
if curr.is_some() {
print!(" ↔ ");
}
}
println!(" -> null");
}
}
fn main() {
let mut dll = DoublyLinkedList::new();
dll.append(1);
dll.append(2);
dll.append(3);
dll.append(4);
dll.append(5);
dll.delete_from_end();
dll.print_list();
}check if list is empty or get current tail to delete
let prev = old_tail.borrow_mut().prev.take();
get previous node of tail to update links
prev_rc.borrow_mut().next = None; // unlink last node
remove last node by setting previous node's next to null
self.tail = Some(prev_rc); // update tail
update tail pointer to new last node
self.head = None; self.tail = None;
handle case when list had only one node, now empty