mirror of
https://github.com/Noratrieb/datastructures.git
synced 2026-01-15 18:05:02 +01:00
get
This commit is contained in:
parent
1c520dce45
commit
b58312c196
1 changed files with 77 additions and 9 deletions
|
|
@ -1,5 +1,9 @@
|
|||
use std::fmt::Debug;
|
||||
use std::ptr::NonNull;
|
||||
|
||||
type NodePtr<T> = Option<NonNull<Node<T>>>;
|
||||
|
||||
/// A doubly linked list with unsafe :O, except it's kind of shit compared to the std one
|
||||
#[derive(Debug)]
|
||||
pub struct LinkedList<T> {
|
||||
start: Option<NonNull<Node<T>>>,
|
||||
|
|
@ -15,19 +19,66 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Node<T> {
|
||||
value: T,
|
||||
next: Option<NonNull<Node<T>>>,
|
||||
prev: Option<NonNull<Node<T>>>,
|
||||
next: NodePtr<T>,
|
||||
prev: NodePtr<T>,
|
||||
}
|
||||
|
||||
impl<T> LinkedList<T> {
|
||||
pub fn new() -> Self<T> {
|
||||
/// Creates a new empty Linked List
|
||||
pub fn new() -> LinkedList<T> {
|
||||
Self {
|
||||
start: None,
|
||||
end: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Prepend an element to the start of the list
|
||||
pub fn prepend(&mut self, element: T) {
|
||||
match self.start {
|
||||
None => {
|
||||
let node = allocate_nonnull(Node {
|
||||
value: element,
|
||||
next: None,
|
||||
prev: None,
|
||||
});
|
||||
self.start = Some(node);
|
||||
self.end = Some(node);
|
||||
}
|
||||
Some(mut node) => {
|
||||
let new = allocate_nonnull(Node {
|
||||
value: element,
|
||||
next: Some(node),
|
||||
prev: None,
|
||||
});
|
||||
unsafe { node.as_mut() }.prev = Some(new);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Random access over the list
|
||||
pub fn get(&self, index: usize) -> Option<&T> {
|
||||
dbg!(self);
|
||||
Self::get_inner(self.start.as_ref(), index).map(|n| &n.value)
|
||||
}
|
||||
|
||||
fn get_inner(node: Option<&NonNull<Node<T>>>, index: usize) -> Option<&Node<T>> {
|
||||
if let Some(ptr) = node {
|
||||
match index {
|
||||
0 => unsafe { Some(ptr.as_ref()) },
|
||||
n => LinkedList::get_inner(Some(ptr), n - 1),
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn allocate_nonnull<T>(element: T) -> NonNull<T> {
|
||||
let mut boxed = Box::new(element);
|
||||
NonNull::new(boxed.as_mut()).expect("Allocation returned null pointer")
|
||||
}
|
||||
|
||||
impl<T> IntoIterator for LinkedList<T> {
|
||||
|
|
@ -40,7 +91,7 @@ impl<T> IntoIterator for LinkedList<T> {
|
|||
}
|
||||
|
||||
pub struct IntoIter<T> {
|
||||
item: Option<NonNull<Node<T>>>,
|
||||
item: NodePtr<T>,
|
||||
}
|
||||
|
||||
impl<T> IntoIter<T> {
|
||||
|
|
@ -53,12 +104,29 @@ impl<T> Iterator for IntoIter<T> {
|
|||
type Item = T;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let next = self.item.take();
|
||||
let ptr = match next {
|
||||
None => return None,
|
||||
Some(mut ptr) => unsafe { ptr.as_mut() },
|
||||
};
|
||||
//let next = self.item.take();
|
||||
//let ptr = match next {
|
||||
// None => return None,
|
||||
// Some(mut ptr) => unsafe { ptr.as_mut() },
|
||||
//};
|
||||
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn random_access() {
|
||||
let mut list = LinkedList::new();
|
||||
list.prepend("hallo");
|
||||
list.prepend("test");
|
||||
list.prepend("nice");
|
||||
assert_eq!(list.get(0), Some(&"nice"));
|
||||
assert_eq!(list.get(1), Some(&"test"));
|
||||
assert_eq!(list.get(2), Some(&"hallo"));
|
||||
assert_eq!(list.get(3), None);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue