Add double linked list
This commit is contained in:
parent
f1f57a76e1
commit
bd0b6e17a5
@ -1,5 +1,6 @@
|
||||
mod simulator;
|
||||
mod kernel;
|
||||
pub mod utility;
|
||||
|
||||
use simulator::machine::Machine;
|
||||
|
||||
|
142
src/utility/list.rs
Normal file
142
src/utility/list.rs
Normal file
@ -0,0 +1,142 @@
|
||||
use std::{cell::RefCell, rc::Rc};
|
||||
|
||||
/// Definition of an element of the list
|
||||
///
|
||||
/// Contain one stored item and the previous/next element of the list
|
||||
struct ListNode<T> {
|
||||
item: T,
|
||||
next: Link<T>,
|
||||
prev: Link<T>,
|
||||
}
|
||||
|
||||
impl<T> ListNode<T> {
|
||||
fn new(item: T) -> Self {
|
||||
Self {
|
||||
item,
|
||||
next: None,
|
||||
prev: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type Link<T> = Option<Rc<RefCell<ListNode<T>>>>;
|
||||
|
||||
/// Defintion of the generic linked list
|
||||
#[derive(Default)]
|
||||
pub struct DoublyLinkedList<T> {
|
||||
head: Link<T>,
|
||||
tail: Link<T>,
|
||||
size: usize,
|
||||
}
|
||||
|
||||
impl<T> DoublyLinkedList<T> {
|
||||
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
head: None,
|
||||
tail: None,
|
||||
size: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.len() == 0
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
self.size
|
||||
}
|
||||
|
||||
/// Add the item at the end of the list
|
||||
pub fn push_back(&mut self, item: T) {
|
||||
let node = Rc::new(RefCell::new(ListNode::new(item)));
|
||||
if let Some(prev_tail) = self.tail.take() {
|
||||
prev_tail.borrow_mut().next = Some(Rc::clone(&node));
|
||||
node.borrow_mut().prev = Some(prev_tail);
|
||||
self.tail = Some(node);
|
||||
self.size += 1;
|
||||
} else {
|
||||
self.head = Some(Rc::clone(&node));
|
||||
self.tail = Some(node);
|
||||
self.size = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/// Add the item at the start of the list
|
||||
pub fn push_front(&mut self, item: T) {
|
||||
let node = Rc::new(RefCell::new(ListNode::new(item)));
|
||||
if let Some(prev_head) = self.head.take() {
|
||||
prev_head.borrow_mut().prev = Some(Rc::clone(&node));
|
||||
node.borrow_mut().next = Some(prev_head);
|
||||
self.head = Some(node);
|
||||
self.size += 1;
|
||||
} else {
|
||||
self.head = Some(Rc::clone(&node));
|
||||
self.tail = Some(node);
|
||||
self.size = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/// Remove the item at the end of the list
|
||||
pub fn pop_back(&mut self) -> Option<T> {
|
||||
self.tail.take().map(|prev_tail| {
|
||||
self.size -= 1;
|
||||
match prev_tail.borrow_mut().prev.take() {
|
||||
Some(node) => {
|
||||
node.borrow_mut().next = None;
|
||||
self.tail = Some(node);
|
||||
}
|
||||
None => {
|
||||
self.head.take();
|
||||
}
|
||||
}
|
||||
Rc::try_unwrap(prev_tail).ok().unwrap().into_inner().item
|
||||
})
|
||||
}
|
||||
|
||||
/// Remove the item at the start of the list
|
||||
pub fn pop_front(&mut self) -> Option<T> {
|
||||
self.head.take().map(|prev_head| {
|
||||
self.size -= 1;
|
||||
match prev_head.borrow_mut().next.take() {
|
||||
Some(node) => {
|
||||
node.borrow_mut().prev = None;
|
||||
self.head = Some(node);
|
||||
}
|
||||
None => {
|
||||
self.tail.take();
|
||||
}
|
||||
}
|
||||
Rc::try_unwrap(prev_head).ok().unwrap().into_inner().item
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl<T> Drop for DoublyLinkedList<T> {
|
||||
/// list destructor, safely desallocate smart pointer Rc
|
||||
fn drop(&mut self) {
|
||||
while let Some(node) = self.head.take() {
|
||||
let _ = node.borrow_mut().prev.take();
|
||||
self.head = node.borrow_mut().next.take();
|
||||
}
|
||||
self.tail.take();
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
|
||||
use super::DoublyLinkedList;
|
||||
|
||||
#[test]
|
||||
fn test_list_push() {
|
||||
let mut list = DoublyLinkedList::new();
|
||||
list.push_back(5);
|
||||
list.push_front(45);
|
||||
assert_eq!(list.pop_front().unwrap(), 45);
|
||||
assert_eq!(list.pop_front().unwrap(), 5);
|
||||
}
|
||||
|
||||
|
||||
}
|
1
src/utility/mod.rs
Normal file
1
src/utility/mod.rs
Normal file
@ -0,0 +1 @@
|
||||
pub mod list;
|
Loading…
Reference in New Issue
Block a user