Struct orx_linked_list::List
source · pub struct List<'a, V, T>where
T: 'a,
V: ListVariant<'a, T>,
V::Ends: ListEnds<'a, V, T>,{ /* private fields */ }
Expand description
Core structure for singly and doubly linked lists:
type SinglyLinkedList<'a, T> = List<'a, Singly, T>;
type DoublyLinkedList<'a, T> = List<'a, Doubly, T>;
§Examples
Below is the simple usage of a doubly linked list.
use orx_linked_list::*;
// empty
let doubly = DoublyLinkedList::<i32>::new();
let doubly = List::<Doubly, i32>::new();
// from iter
let doubly: DoublyLinkedList<_> = [1, 2, 3].into_iter().collect();
let mut doubly: List<Doubly, _> = [1, 2, 3].into_iter().collect();
assert_eq!(Some(&1), doubly.front());
assert_eq!(Some(&3), doubly.back());
doubly.push_front(0);
doubly.push_back(4);
assert_eq!(Some(&0), doubly.front());
assert_eq!(Some(&4), doubly.back());
assert_eq!(Some(0), doubly.pop_front());
assert_eq!(Some(4), doubly.pop_back());
assert_eq!(vec![1, 2, 3], doubly.iter().copied().collect::<Vec<_>>());
assert_eq!(vec![3, 2, 1], doubly.iter_from_back().copied().collect::<Vec<_>>());
Using a singly linked list can be used instead by using the SinglyLinkedList
type alias or changing the variant from Doubly
to Singly
.
use orx_linked_list::*;
// empty
let singly = SinglyLinkedList::<i32>::new();
let singly = List::<Singly, i32>::new();
// from iter
let singly: SinglyLinkedList<_> = [1, 2, 3].into_iter().collect();
let mut singly: List<Singly, _> = [1, 2, 3].into_iter().collect();
assert_eq!(Some(&1), singly.front());
assert_eq!(Some(&3), singly.back());
singly.push_front(0);
assert_eq!(Some(&0), singly.front());
assert_eq!(Some(0), singly.pop_front());
assert_eq!(vec![1, 2, 3], singly.iter().copied().collect::<Vec<_>>());
Implementations§
source§impl<'a, V, T: 'a> List<'a, V, T>where
V: ListVariant<'a, T>,
V::Ends: ListEnds<'a, V, T>,
impl<'a, V, T: 'a> List<'a, V, T>where
V: ListVariant<'a, T>,
V::Ends: ListEnds<'a, V, T>,
sourcepub fn new() -> Self
pub fn new() -> Self
Creates an empty list.
§Examples
use orx_linked_list::*;
let list: List<Singly, char> = List::new();
assert!(list.is_empty());
sourcepub fn len(&self) -> usize
pub fn len(&self) -> usize
Returns the number of elements in the list.
§Examples
use orx_linked_list::*;
let mut list: List<Doubly, char> = List::new();
assert_eq!(0, list.len());
list.push_back('a');
list.push_front('b');
_ = list.pop_back();
list.push_back('c');
assert_eq!(2, list.len());
sourcepub fn is_empty(&self) -> bool
pub fn is_empty(&self) -> bool
Returns the number of elements in the list.
§Examples
use orx_linked_list::*;
let mut list = List::<Doubly, _>::new();
assert!(list.is_empty());
list.push_back('a');
assert!(!list.is_empty());
_ = list.pop_back();
assert!(list.is_empty());
sourcepub fn front(&self) -> Option<&T>
pub fn front(&self) -> Option<&T>
O(1) Returns a reference to the front of the list.
§Examples
use orx_linked_list::*;
let mut list = List::<Singly, _>::new();
assert!(list.front().is_none());
list.push_front('a');
assert_eq!(Some(&'a'), list.front());
list.push_front('b');
assert_eq!(Some(&'b'), list.front());
_ = list.pop_front();
assert_eq!(Some(&'a'), list.front());
sourcepub fn back(&self) -> Option<&T>
pub fn back(&self) -> Option<&T>
O(1) Returns a reference to the back of the list.
§Examples
use orx_linked_list::*;
let mut list = List::<Doubly, _>::new();
assert!(list.back().is_none());
list.push_back('a');
assert_eq!(Some(&'a'), list.back());
list.push_back('b');
assert_eq!(Some(&'b'), list.back());
list.push_front('c');
assert_eq!(Some(&'b'), list.back());
_ = list.pop_back();
assert_eq!(Some(&'a'), list.back());
sourcepub fn iter(&self) -> IterForward<'_, 'a, V, T>
pub fn iter(&self) -> IterForward<'_, 'a, V, T>
O(n) Returns an iterator to elements of the list from the front
node to the back.
Time complexity:
- O(1) to access the front node.
- O(n) to iterate forward from the given node.
§Examples
use orx_linked_list::*;
let mut list = List::<Doubly, _>::new();
list.push_front('b');
list.push_back('c');
list.push_front('a');
let mut iter = list.iter();
assert_eq!(Some(&'a'), iter.next());
assert_eq!(Some(&'b'), iter.next());
assert_eq!(Some(&'c'), iter.next());
assert!(iter.next().is_none());
sourcepub fn iter_forward_from(
&self,
node_index: NodeIndex<'a, V, T>,
) -> Result<IterForward<'_, 'a, V, T>, NodeIndexError>
pub fn iter_forward_from( &self, node_index: NodeIndex<'a, V, T>, ) -> Result<IterForward<'_, 'a, V, T>, NodeIndexError>
O(n) Creates a forward iterator starting from the node with the given node_index
.
Returns the corresponding NodeIndexError
if the given index is invalid for this linked list.
Time complexity:
- O(1) to access the front node.
- O(n) to iterate forward from the given node.
§Examples
use orx_linked_list::*;
let mut list = List::<Doubly, _>::new();
let b = list.push_front('b');
list.push_back('c');
list.push_front('a');
list.push_back('d'); // list: [a-b-c-d]
let mut iter = list.iter_forward_from(b);
assert!(iter.is_ok());
let mut iter = iter.unwrap();
assert_eq!(Some(&'b'), iter.next());
assert_eq!(Some(&'c'), iter.next());
assert_eq!(Some(&'d'), iter.next());
assert_eq!(None, iter.next());
sourcepub fn clear(&mut self)
pub fn clear(&mut self)
Clears the list removing all elements.
§Examples
use orx_linked_list::*;
let mut list = List::<Doubly, _>::new();
list.push_front('b');
list.push_back('c');
list.push_front('a');
assert_eq!(3, list.len());
assert_eq!(&['a', 'b', 'c'], list.iter().copied().collect::<Vec<_>>().as_slice());
list.clear();
assert!(list.is_empty());
sourcepub fn swap_front(&mut self, new_front: T) -> Option<T>
pub fn swap_front(&mut self, new_front: T) -> Option<T>
O(1) Sets value of front
of the list as new_front
and returns value of the front element; returns None if list was empty.
§Examples
use orx_linked_list::*;
let mut list: List<Doubly, _> = List::new();
assert_eq!(0, list.len());
let prior_front = list.swap_front('a');
assert!(prior_front.is_none());
assert_eq!(Some(&'a'), list.front());
let prior_front = list.swap_front('z');
assert_eq!(Some('a'), prior_front);
assert_eq!(Some(&'z'), list.front());
sourcepub fn swap_back(&mut self, new_back: T) -> Option<T>
pub fn swap_back(&mut self, new_back: T) -> Option<T>
O(1) Sets value of back
of the list as new_back
and returns value of the back element; returns None if list was empty.
§Examples
use orx_linked_list::*;
let mut list: List<Doubly, _> = List::new();
assert_eq!(0, list.len());
let prior_back = list.swap_back('a');
assert!(prior_back.is_none());
assert_eq!(Some(&'a'), list.back());
let prior_back = list.swap_back('z');
assert_eq!(Some('a'), prior_back);
assert_eq!(Some(&'z'), list.back());
sourcepub fn pop_front(&mut self) -> Option<T>
pub fn pop_front(&mut self) -> Option<T>
O(1) Pops and returns the value
at the front
of the list; returns None if the list is empty.
§Examples
use orx_linked_list::*;
let mut list: List<Singly, char> = List::new();
let popped = list.pop_front();
assert!(popped.is_none());
list.push_front('a');
assert_eq!(Some(&'a'), list.front());
let popped = list.pop_front();
assert_eq!(Some('a'), popped);
assert!(list.is_empty());
sourcepub fn get(&self, node_index: NodeIndex<'a, V, T>) -> Option<&T>
pub fn get(&self, node_index: NodeIndex<'a, V, T>) -> Option<&T>
O(1) Returns a reference to the node with the given node_index
in constant time.
Returns None if the index is invalid.
§Safety
get(node_index)
returns Some
if all of of the following safety and correctness conditions hold:
- the index is created from this linked list,
- the node that this index is created for still belongs to the list`; i.e., it is not removed,
- the node positions in this list are not reorganized to reclaim memory:
- this case is never observed if
MemoryReclaimNever
is used, - this case is observed when:
- the memory reclaim policy is
MemoryReclaimOnThreshold
, and - the utilization of active nodes has dropped a threshold due to pop and remove operations.
- the memory reclaim policy is
- this case is never observed if
§Examples
use orx_linked_list::*;
let mut list = List::<Doubly, _>::new();
let a = list.push_back('a');
let b = list.push_back('b');
assert_eq!(Some(&'a'), list.get(a));
assert_eq!(Some(&'b'), list.get(b));
list.push_front('c');
list.push_back('d');
list.push_front('e');
list.push_back('f');
assert_eq!(Some(&'a'), list.get(a));
assert_eq!(Some(&'b'), list.get(b));
list.clear();
assert_eq!(None, list.get(a));
assert_eq!(None, list.get(b));
sourcepub fn get_or_error(
&self,
node_index: NodeIndex<'a, V, T>,
) -> Result<&T, NodeIndexError>
pub fn get_or_error( &self, node_index: NodeIndex<'a, V, T>, ) -> Result<&T, NodeIndexError>
O(1) Returns a reference to the node with the given node_index
in constant time.
Returns None if the index is invalid.
§Safety
get(node_index)
returns Some
if all of of the following safety and correctness conditions hold:
- the index is created from this linked list,
- the node that this index is created for still belongs to the list`; i.e., it is not removed,
- the node positions in this list are not reorganized to reclaim memory:
- this case is never observed if
MemoryReclaimNever
is used, - this case is observed when:
- the memory reclaim policy is
MemoryReclaimOnThreshold
, and - the utilization of active nodes has dropped a threshold due to pop and remove operations.
- the memory reclaim policy is
- this case is never observed if
§Examples
use orx_linked_list::*;
let mut list = List::<Doubly, _>::new();
let a = list.push_back('a');
let b = list.push_back('b');
assert_eq!(Ok(&'a'), list.get_or_error(a));
assert_eq!(Ok(&'b'), list.get_or_error(b));
list.push_back('c');
list.push_back('d');
list.push_back('e');
list.push_back('f');
assert_eq!(
vec!['a', 'b', 'c', 'd', 'e', 'f'],
list.iter().copied().collect::<Vec<_>>()
);
assert_eq!(Ok(&'a'), list.get_or_error(a));
assert_eq!(Ok(&'b'), list.get_or_error(b));
let removed = list.remove(a);
assert_eq!(removed, Ok('a'));
assert_eq!(Err(NodeIndexError::RemovedNode), list.get_or_error(a));
assert_eq!(Ok(&'b'), list.get_or_error(b));
sourcepub fn index_of(&self, value: &T) -> Option<NodeIndex<'a, V, T>>where
T: PartialEq,
pub fn index_of(&self, value: &T) -> Option<NodeIndex<'a, V, T>>where
T: PartialEq,
O(n) Performs a forward search from the front and returns the index of the first node with value equal to the given value
.
Returns None if there is no element with the given value.
Obtained NodeIndex
can later be used for constant time access to the corresponding element.
§Examples
use orx_linked_list::*;
use orx_selfref_col::NodeIndexError;
let mut list = List::<Doubly, _>::from_iter(['a', 'b', 'c', 'd']);
let x = list.index_of(&'x');
assert!(x.is_none());
let b = list.index_of(&'b'); // O(n)
assert!(b.is_some());
let b = b.unwrap();
let data_b = list.get(b); // O(1)
assert_eq!(data_b, Some(&'b'));
// O(1) to create the iterators from the index
assert_eq!(&['b', 'c', 'd'], list.iter_forward_from(b).unwrap().copied().collect::<Vec<_>>().as_slice());
assert_eq!(&['b', 'a'], list.iter_backward_from(b).unwrap().copied().collect::<Vec<_>>().as_slice());
list.insert_prev_to(b, 'X').unwrap(); // O(1)
list.insert_next_to(b, 'Y').unwrap(); // O(1)
assert_eq!(&['a', 'X', 'b', 'Y', 'c', 'd'], list.iter().copied().collect::<Vec<_>>().as_slice());
let removed = list.remove(b); // O(1)
assert_eq!(removed, Ok('b'));
assert_eq!(&['a', 'X', 'Y', 'c', 'd'], list.iter().copied().collect::<Vec<_>>().as_slice());
assert_eq!(list.get(b), None);
assert_eq!(list.get_or_error(b).err(), Some(NodeIndexError::RemovedNode));
sourcepub fn contains(&self, value: &T) -> boolwhere
T: PartialEq,
pub fn contains(&self, value: &T) -> boolwhere
T: PartialEq,
O(n) Performs a forward search from the front and returns true
if there exists a node with value equal to the given value
.
Returns false if there is no element with the given value.
§Examples
use orx_linked_list::*;
let mut list = List::<Doubly, _>::from_iter(['a', 'b', 'c', 'd']);
assert!(list.contains(&'a'));
assert!(!list.contains(&'x'));
sourcepub fn position_of(&self, value: &T) -> Option<usize>where
T: PartialEq,
pub fn position_of(&self, value: &T) -> Option<usize>where
T: PartialEq,
O(n) Performs a forward search from the front and returns the position of the first node with value equal to the given value
.
Returns None if there is no element with the given value.
Note that, unlike vectors, the position of an element does not provide a constant time access to the element.
In order to obtain a NodeIndex
allowing O(1) access, use the index_of
method;
or store the node index returned when the element is added to the list for the first time by methods such as push_front
or insert_next_to
, etc.
§Examples
use orx_linked_list::*;
use orx_selfref_col::NodeIndexError;
let mut list = List::<Doubly, _>::from_iter(['a', 'b', 'c', 'd']);
let x = list.position_of(&'x');
assert_eq!(x, None);
let b = list.position_of(&'b'); // O(n)
assert_eq!(b, Some(1));
sourcepub fn node_utilization(&self) -> f32
pub fn node_utilization(&self) -> f32
Returns the node utilization as a fraction of active nodes to the used nodes:
- 1.0 when there is no closed node;
- 0.0 when all used memory is used by closed nodes.
Node utilization can be brought to 100%:
- automatically by the underlying memory policy if
MemoryReclaimOnThreshold
is used; or - manually by calling the
reclaim_closed_nodes
method.
It is important to note that, memory reclaim operation leads to reorganization of the nodes, which invalidates the node indices obtained before the process.
§Examples
use orx_linked_list::*;
fn float_eq(x: f32, y: f32) -> bool {
(x - y).abs() < f32::EPSILON
}
// MemoryReclaimOnThreshold<2> -> memory will be reclaimed when utilization is below 75%
let mut list = List::<Doubly, _>::new();
let a = list.push_back('a');
list.push_back('b');
list.push_back('c');
list.push_back('d');
list.push_back('e');
assert!(float_eq(list.node_utilization(), 1.00)); // utilization = 5/5 = 100%
// no reorganization; 'a' is still valid
assert_eq!(list.get_or_error(a), Ok(&'a'));
assert_eq!(list.get(a), Some(&'a'));
_ = list.pop_back(); // leaves a hole
assert!(float_eq(list.node_utilization(), 0.80)); // utilization = 4/5 = 80%
// no reorganization; 'a' is still valid
assert_eq!(list.get_or_error(a), Ok(&'a'));
assert_eq!(list.get(a), Some(&'a'));
_ = list.pop_back(); // leaves the second hole; we have utilization = 3/5 = 60%
// this is below the threshold 75%, and triggers reclaim
// we claim the two unused nodes / holes
assert!(float_eq(list.node_utilization(), 1.00)); // utilization = 3/3 = 100%
// nodes reorganized; 'a' is no more valid
assert_eq!(
list.get_or_error(a),
Err(NodeIndexError::ReorganizedCollection)
);
assert_eq!(list.get(a), None);
sourcepub fn reclaim_closed_nodes(&mut self)
pub fn reclaim_closed_nodes(&mut self)
Manually attempts to reclaim closed nodes.
§Safety
It is important to note that, memory reclaim operation leads to reorganization of the nodes, which invalidates the node indices obtained before the process.
§Examples
use orx_linked_list::*;
fn float_eq(x: f32, y: f32) -> bool {
(x - y).abs() < f32::EPSILON
}
// MemoryReclaimNever -> memory will never be reclaimed automatically
let mut list = List::<Doubly<MemoryReclaimNever>, _>::new();
let a = list.push_back('a');
list.push_back('b');
list.push_back('c');
list.push_back('d');
list.push_back('e');
assert!(float_eq(list.node_utilization(), 1.00)); // utilization = 5/5 = 100%
// no reorganization; 'a' is still valid
assert_eq!(list.get_or_error(a), Ok(&'a'));
assert_eq!(list.get(a), Some(&'a'));
_ = list.pop_back(); // leaves a hole
_ = list.pop_back(); // leaves the second hole
_ = list.pop_back(); // leaves the third hole
assert!(float_eq(list.node_utilization(), 0.40)); // utilization = 2/5 = 40%
// still no reorganization; 'a' is and will always be valid unless we manually reclaim
assert_eq!(list.get_or_error(a), Ok(&'a'));
assert_eq!(list.get(a), Some(&'a'));
list.reclaim_closed_nodes();
// we can manually reclaim memory any time we want to maximize utilization
assert!(float_eq(list.node_utilization(), 1.00)); // utilization = 2/2 = 100%
// we are still protected by list & index validation
// nodes reorganized; 'a' is no more valid, we cannot wrongly use the index
assert_eq!(
list.get_or_error(a),
Err(NodeIndexError::ReorganizedCollection)
);
assert_eq!(list.get(a), None);
source§impl<'a, T: 'a, M> List<'a, Singly<M>, T>where
M: MemoryReclaimPolicy,
impl<'a, T: 'a, M> List<'a, Singly<M>, T>where
M: MemoryReclaimPolicy,
sourcepub fn push_front(&mut self, value: T) -> NodeIndex<'a, Singly<M>, T>
pub fn push_front(&mut self, value: T) -> NodeIndex<'a, Singly<M>, T>
O(1) Pushes the value
to the front
of the list.
§Examples
use orx_linked_list::*;
let mut list: List<Singly, char> = List::new();
list.push_front('a');
assert_eq!(Some(&'a'), list.front());
list.push_front('b');
assert_eq!(Some(&'b'), list.front());
let popped = list.pop_front();
assert_eq!(Some('b'), popped);
assert_eq!(Some(&'a'), list.front());
sourcepub fn append_front(&mut self, other: Self)
pub fn append_front(&mut self, other: Self)
O(1) Appends the other
list to the front
of this list.
Time complexity:
- O(1) gets
front
of this list, say a, - O(1) gets
back
of the other list, say b, - O(1) connects
b -> a
.
§Examples
use orx_linked_list::*;
let mut list: List<Singly, char> = List::new();
list.push_front('c');
list.push_front('b');
list.push_front('a');
let mut other: List<Singly, char> = List::new();
other.push_front('e');
other.push_front('d');
list.append_front(other);
assert_eq!(&['d', 'e', 'a', 'b', 'c'], list.iter().copied().collect::<Vec<_>>().as_slice());
sourcepub fn append_back(&mut self, other: Self)
pub fn append_back(&mut self, other: Self)
O(1) Appends the other
list to the back
of this list.
Time complexity:
- O(1) gets
back
of this list, say a, - O(1) gets
front
of the other list, say b, - O(1) connects
a -> b
.
§Examples
use orx_linked_list::*;
let mut list: List<Singly, char> = List::new();
list.push_front('c');
list.push_front('b');
list.push_front('a');
let mut other: List<Singly, char> = List::new();
other.push_front('e');
other.push_front('d');
list.append_back(other);
assert_eq!(&['a', 'b', 'c', 'd', 'e'], list.iter().copied().collect::<Vec<_>>().as_slice());
sourcepub fn remove_at(&mut self, at: usize) -> Option<T>
pub fn remove_at(&mut self, at: usize) -> Option<T>
O(n) Removes and returns value of the at
-th element in the list; returns None if list length is less than or equal to at
.
Time complexity:
- starts from the
front
, - O(n) iterates until reaching the element,
- O(1) removes and returns the value.
§Example
use orx_linked_list::*;
let mut list = List::<Singly, char>::new();
list.push_front('c');
list.push_front('b');
list.push_front('a');
assert_eq!(&['a', 'b', 'c'], list.iter().copied().collect::<Vec<_>>().as_slice());
let removed = list.remove_at(3);
assert!(removed.is_none());
assert_eq!(&['a', 'b', 'c'], list.iter().copied().collect::<Vec<_>>().as_slice());
let removed = list.remove_at(1);
assert_eq!(Some('b'), removed);
assert_eq!(&['a', 'c'], list.iter().copied().collect::<Vec<_>>().as_slice());
sourcepub fn insert_at(&mut self, at: usize, value: T) -> NodeIndex<'a, Singly<M>, T>
pub fn insert_at(&mut self, at: usize, value: T) -> NodeIndex<'a, Singly<M>, T>
O(n) Inserts the given value
at the at
-th element of the list.
Time complexity:
- starts from the
front
, - O(n) iterates until reaching the element,
- O(1) inserts the value.
§Panics
Panics if at > self.len()
.
§Example
use orx_linked_list::*;
let mut list = List::<Singly, char>::new();
list.push_front('c');
list.push_front('b');
list.push_front('a');
assert_eq!(&['a', 'b', 'c'], list.iter().copied().collect::<Vec<_>>().as_slice());
list.insert_at(1, 'x');
assert_eq!(&['a', 'x', 'b', 'c'], list.iter().copied().collect::<Vec<_>>().as_slice());
sourcepub fn retain<Predicate>(&mut self, predicate: &Predicate)
pub fn retain<Predicate>(&mut self, predicate: &Predicate)
O(n) Retains only the elements specified by the predicate.
In other words, removes all elements e
for which predicate(&e)
returns false.
This method operates in place, visiting each element exactly once in the original order, and preserves the order of the retained elements.
Time complexity:
- O(n) to iterate over all elements,
- O(1) to remove elements failing to satisfy the predicate.
§Examples
use orx_linked_list::*;
let mut list = List::<Singly, _>::from_iter([0, 1, 2, 3, 4]);
list.retain(&|x| *x % 2 == 0);
assert_eq!(&[0, 2, 4], list.iter().copied().collect::<Vec<_>>().as_slice());
sourcepub fn retain_collect<Predicate, Collect>(
&mut self,
predicate: &Predicate,
collect: &mut Collect,
)
pub fn retain_collect<Predicate, Collect>( &mut self, predicate: &Predicate, collect: &mut Collect, )
O(n) Retains only the elements specified by the predicate; all elements that are removed elements are collected by the provided closure.
In other words, removes all elements e
for which predicate(&e)
returns false; and calls collect(e)
on the removed values.
This method operates in place, visiting each element exactly once in the original order, and preserves the order of the retained elements.
Time complexity:
- O(n) to iterate over all elements,
- O(1) to remove elements failing to satisfy the predicate and collect.
§Examples
use orx_linked_list::*;
let mut list = List::<Singly, _>::from_iter([0, 1, 2, 3, 4]);
let mut odds = vec![];
let mut collect = |x| odds.push(x);
list.retain_collect(&|x| *x % 2 == 0, &mut collect);
assert_eq!(&[0, 2, 4], list.iter().copied().collect::<Vec<_>>().as_slice());
assert_eq!(&[1, 3], odds.as_slice());
source§impl<'a, T: 'a, M> List<'a, Doubly<M>, T>where
M: MemoryReclaimPolicy,
impl<'a, T: 'a, M> List<'a, Doubly<M>, T>where
M: MemoryReclaimPolicy,
sourcepub fn index_of_from_back(
&self,
value: &T,
) -> Option<NodeIndex<'a, Doubly<M>, T>>where
T: PartialEq,
pub fn index_of_from_back(
&self,
value: &T,
) -> Option<NodeIndex<'a, Doubly<M>, T>>where
T: PartialEq,
O(n) Performs a backward search from the back and returns the index of the first node with value equal to the given value
.
Returns None if there is no element with the given value.
Obtained NodeIndex
can later be used for constant time access to the corresponding element.
§Examples
use orx_linked_list::*;
use orx_selfref_col::NodeIndexError;
let mut list = List::<Doubly, _>::from_iter(['a', 'b', 'c', 'd']);
let x = list.index_of_from_back(&'x');
assert!(x.is_none());
let b = list.index_of_from_back(&'b'); // O(n)
assert!(b.is_some());
let b = b.unwrap();
let data_b = list.get(b); // O(1)
assert_eq!(data_b, Some(&'b'));
// O(1) to create the iterators from the index
assert_eq!(&['b', 'c', 'd'], list.iter_forward_from(b).unwrap().copied().collect::<Vec<_>>().as_slice());
assert_eq!(&['b', 'a'], list.iter_backward_from(b).unwrap().copied().collect::<Vec<_>>().as_slice());
list.insert_prev_to(b, 'X').unwrap(); // O(1)
list.insert_next_to(b, 'Y').unwrap(); // O(1)
assert_eq!(&['a', 'X', 'b', 'Y', 'c', 'd'], list.iter().copied().collect::<Vec<_>>().as_slice());
let removed = list.remove(b); // O(1)
assert_eq!(removed, Ok('b'));
assert_eq!(&['a', 'X', 'Y', 'c', 'd'], list.iter().copied().collect::<Vec<_>>().as_slice());
assert_eq!(list.get(b), None);
assert_eq!(list.get_or_error(b).err(), Some(NodeIndexError::RemovedNode));
sourcepub fn contains_from_back(&self, value: &T) -> boolwhere
T: PartialEq,
pub fn contains_from_back(&self, value: &T) -> boolwhere
T: PartialEq,
O(n) Performs a backward search from the back and returns true
if there exists a node with value equal to the given value
.
Returns false if there is no element with the given value.
§Examples
use orx_linked_list::*;
let mut list = List::<Doubly, _>::from_iter(['a', 'b', 'c', 'd']);
assert!(list.contains_from_back(&'a'));
assert!(!list.contains_from_back(&'x'));
sourcepub fn iter_from_back(&self) -> IterBackward<'_, 'a, Doubly<M>, T>
pub fn iter_from_back(&self) -> IterBackward<'_, 'a, Doubly<M>, T>
O(n) Returns an iterator to elements of the list from the back
node to the front.
§Examples
use orx_linked_list::*;
let mut list = List::<Doubly, _>::new();
list.push_front('b');
list.push_back('c');
list.push_front('a');
let mut iter = list.iter_from_back();
assert_eq!(Some(&'c'), iter.next());
assert_eq!(Some(&'b'), iter.next());
assert_eq!(Some(&'a'), iter.next());
assert!(iter.next().is_none());
sourcepub fn iter_backward_from(
&self,
node_index: NodeIndex<'a, Doubly<M>, T>,
) -> Result<IterBackward<'_, 'a, Doubly<M>, T>, NodeIndexError>
pub fn iter_backward_from( &self, node_index: NodeIndex<'a, Doubly<M>, T>, ) -> Result<IterBackward<'_, 'a, Doubly<M>, T>, NodeIndexError>
O(n) Creates a backward iterator starting from the node with the given node_index
.
Returns the corresponding NodeIndexError
if the given index is invalid for this linked list.
Time complexity:
- O(1) to access the front node.
- O(n) to iterate forward from the given node.
§Examples
use orx_linked_list::*;
let mut list = List::<Doubly, _>::new();
let b = list.push_front('b');
list.push_back('c');
list.push_front('a');
list.push_back('d'); // list: [a-b-c-d]
let mut iter = list.iter_backward_from(b);
assert!(iter.is_ok());
let mut iter = iter.unwrap();
assert_eq!(Some(&'b'), iter.next());
assert_eq!(Some(&'a'), iter.next());
assert_eq!(None, iter.next());
sourcepub fn push_front(&mut self, value: T) -> NodeIndex<'a, Doubly<M>, T>
pub fn push_front(&mut self, value: T) -> NodeIndex<'a, Doubly<M>, T>
O(1) Pushes the value
to the front
of the list.
§Examples
use orx_linked_list::*;
let mut list: List<Doubly, char> = List::new();
list.push_front('a');
assert_eq!(Some(&'a'), list.front());
list.push_front('b');
assert_eq!(Some(&'b'), list.front());
let popped = list.pop_front();
assert_eq!(Some('b'), popped);
assert_eq!(Some(&'a'), list.front());
sourcepub fn push_back(&mut self, value: T) -> NodeIndex<'a, Doubly<M>, T>
pub fn push_back(&mut self, value: T) -> NodeIndex<'a, Doubly<M>, T>
O(1) Pushes the value
to the back
of the list.
§Examples
use orx_linked_list::*;
let mut list: List<Doubly, char> = List::new();
list.push_back('a');
assert_eq!(Some(&'a'), list.back());
list.push_back('b');
assert_eq!(Some(&'b'), list.back());
let popped = list.pop_back();
assert_eq!(Some('b'), popped);
assert_eq!(Some(&'a'), list.back());
sourcepub fn append_front(&mut self, other: Self)
pub fn append_front(&mut self, other: Self)
O(1) Appends the other
list to the front
of this list.
Time complexity:
- O(1) gets
front
of this list, say a, - O(1) gets
back
of the other list, say b, - O(1) connects
b -> a
.
§Examples
use orx_linked_list::*;
let mut list: List<Doubly, char> = List::new();
list.push_front('b');
list.push_front('a');
list.push_back('c');
let mut other: List<Doubly, char> = List::new();
other.push_back('d');
other.push_back('e');
list.append_front(other);
assert_eq!(&['d', 'e', 'a', 'b', 'c'], list.iter().copied().collect::<Vec<_>>().as_slice());
sourcepub fn append_back(&mut self, other: Self)
pub fn append_back(&mut self, other: Self)
O(1) Appends the other
list to the back
of this list.
Time complexity:
- O(1) gets
back
of this list, say a, - O(1) gets
front
of the other list, say b, - O(1) connects
a -> b
.
§Examples
use orx_linked_list::*;
let mut list: List<Doubly, char> = List::new();
list.push_front('b');
list.push_front('a');
list.push_back('c');
let mut other: List<Doubly, char> = List::new();
other.push_back('d');
other.push_back('e');
list.append_back(other);
assert_eq!(&['a', 'b', 'c', 'd', 'e'], list.iter().copied().collect::<Vec<_>>().as_slice());
sourcepub fn pop_back(&mut self) -> Option<T>
pub fn pop_back(&mut self) -> Option<T>
O(1) Pops and returns the value
at the back
of the list; returns None if the list is empty.
§Examples
use orx_linked_list::*;
let mut list: List<Doubly, char> = List::new();
let popped = list.pop_back();
assert!(popped.is_none());
list.push_back('a');
assert_eq!(Some(&'a'), list.back());
let popped = list.pop_back();
assert_eq!(Some('a'), popped);
assert!(list.is_empty());
sourcepub fn remove_at(&mut self, at: usize) -> Option<T>
pub fn remove_at(&mut self, at: usize) -> Option<T>
O(n) Removes and returns value of the at
-th element in the list; returns None if list length is less than or equal to at
.
Time complexity:
- starts from the
front
orback
choosing the shorter path depending on the length of the list and value ofat
, - O(n) iterates until reaching the element,
- O(1) removes and returns the value.
§Example
use orx_linked_list::*;
let mut list = List::<Doubly, char>::new();
list.push_front('b');
list.push_back('c');
list.push_front('a');
assert_eq!(&['a', 'b', 'c'], list.iter().copied().collect::<Vec<_>>().as_slice());
let removed = list.remove_at(3);
assert!(removed.is_none());
assert_eq!(&['a', 'b', 'c'], list.iter().copied().collect::<Vec<_>>().as_slice());
let removed = list.remove_at(1);
assert_eq!(Some('b'), removed);
assert_eq!(&['a', 'c'], list.iter().copied().collect::<Vec<_>>().as_slice());
sourcepub fn remove(
&mut self,
node_index: NodeIndex<'a, Doubly<M>, T>,
) -> Result<T, NodeIndexError>
pub fn remove( &mut self, node_index: NodeIndex<'a, Doubly<M>, T>, ) -> Result<T, NodeIndexError>
O(1) Removes and returns value of the element with the given node_index
.
Does not change the list and returns the NodeIndexError
if the node index is invalid.
§Safety
Removal is carried out only if the node_index
is valid.
And the node index is valid if all of of the following safety and correctness conditions hold:
- the index is created from this linked list,
- the node that this index is created for still belongs to the list`; i.e., it is not removed,
- the node positions in this list are not reorganized to reclaim memory:
- this case is never observed if
MemoryReclaimNever
is used, - this case is observed when:
- the memory reclaim policy is
MemoryReclaimOnThreshold
, and - the utilization of active nodes has dropped a threshold due to pop and remove operations.
- the memory reclaim policy is
- this case is never observed if
§Examples
use orx_linked_list::*;
use orx_selfref_col::NodeIndexError;
let mut list = List::<Doubly, _>::new();
list.push_back('a');
let b = list.push_back('b');
list.push_back('c');
list.push_back('d');
assert_eq!(vec!['a', 'b', 'c', 'd'], list.iter().copied().collect::<Vec<_>>());
let removed = list.remove(b);
assert_eq!(removed, Ok('b'));
assert_eq!(vec!['a', 'c', 'd'], list.iter().copied().collect::<Vec<_>>());
let not_removed = list.remove(b);
assert_eq!(not_removed.err(), Some(NodeIndexError::RemovedNode));
assert_eq!(vec!['a', 'c', 'd'], list.iter().copied().collect::<Vec<_>>());
sourcepub fn insert_at(&mut self, at: usize, value: T) -> NodeIndex<'a, Doubly<M>, T>
pub fn insert_at(&mut self, at: usize, value: T) -> NodeIndex<'a, Doubly<M>, T>
O(n) Inserts the given value
at the at
-th element of the list.
Time complexity:
- starts from the
front
orback
choosing the shorter path depending on the length of the list and value ofat
, - O(n) iterates until reaching the element,
- O(1) inserts the value.
§Panics
Panics if at > self.len()
.
§Example
use orx_linked_list::*;
let mut list = List::<Doubly, char>::new();
list.push_back('c');
list.push_front('b');
list.push_front('a');
assert_eq!(&['a', 'b', 'c'], list.iter().copied().collect::<Vec<_>>().as_slice());
list.insert_at(1, 'x');
assert_eq!(&['a', 'x', 'b', 'c'], list.iter().copied().collect::<Vec<_>>().as_slice());
sourcepub fn insert_prev_to(
&mut self,
node_index: NodeIndex<'a, Doubly<M>, T>,
value: T,
) -> Result<NodeIndex<'a, Doubly<M>, T>, NodeIndexError>
pub fn insert_prev_to( &mut self, node_index: NodeIndex<'a, Doubly<M>, T>, value: T, ) -> Result<NodeIndex<'a, Doubly<M>, T>, NodeIndexError>
O(1) Inserts the given value
as the previous of the node with the given node_index
and returns the index of the inserted node.
Does not change the list and returns the NodeIndexError
if the node index is invalid.
§Safety
Insertion is carried out only if the node_index
is valid.
And the node index is valid if all of of the following safety and correctness conditions hold:
- the index is created from this linked list,
- the node that this index is created for still belongs to the list`; i.e., it is not removed,
- the node positions in this list are not reorganized to reclaim memory:
- this case is never observed if
MemoryReclaimNever
is used, - this case is observed when:
- the memory reclaim policy is
MemoryReclaimOnThreshold
, and - the utilization of active nodes has dropped a threshold due to pop and remove operations.
- the memory reclaim policy is
- this case is never observed if
§Examples
use orx_linked_list::*;
let mut list = List::<Doubly, _>::new();
list.push_back('a');
let b = list.push_back('b');
list.push_back('c');
list.push_back('d');
assert_eq!(vec!['a', 'b', 'c', 'd'], list.iter().copied().collect::<Vec<_>>());
let x = list.insert_prev_to(b, 'X').unwrap();
assert_eq!(list.get(x), Some(&'X'));
assert_eq!(vec!['a', 'X', 'b', 'c', 'd'], list.iter().copied().collect::<Vec<_>>());
sourcepub fn insert_next_to(
&mut self,
node_index: NodeIndex<'a, Doubly<M>, T>,
value: T,
) -> Result<NodeIndex<'a, Doubly<M>, T>, NodeIndexError>
pub fn insert_next_to( &mut self, node_index: NodeIndex<'a, Doubly<M>, T>, value: T, ) -> Result<NodeIndex<'a, Doubly<M>, T>, NodeIndexError>
O(1) Inserts the given value
as the next of the node with the given node_index
and returns the index of the inserted node.
Does not change the list and returns the NodeIndexError
if the node index is invalid.
§Safety
Insertion is carried out only if the node_index
is valid.
And the node index is valid if all of of the following safety and correctness conditions hold:
- the index is created from this linked list,
- the node that this index is created for still belongs to the list`; i.e., it is not removed,
- the node positions in this list are not reorganized to reclaim memory:
- this case is never observed if
MemoryReclaimNever
is used, - this case is observed when:
- the memory reclaim policy is
MemoryReclaimOnThreshold
, and - the utilization of active nodes has dropped a threshold due to pop and remove operations.
- the memory reclaim policy is
- this case is never observed if
§Examples
use orx_linked_list::*;
let mut list = List::<Doubly, _>::new();
list.push_back('a');
let b = list.push_back('b');
list.push_back('c');
list.push_back('d');
assert_eq!(vec!['a', 'b', 'c', 'd'], list.iter().copied().collect::<Vec<_>>());
let x = list.insert_next_to(b, 'X').unwrap();
assert_eq!(list.get(x), Some(&'X'));
assert_eq!(vec!['a', 'b', 'X', 'c', 'd'], list.iter().copied().collect::<Vec<_>>());
sourcepub fn retain<Predicate>(&mut self, predicate: &Predicate)
pub fn retain<Predicate>(&mut self, predicate: &Predicate)
O(n) Retains only the elements specified by the predicate.
In other words, removes all elements e
for which predicate(&e)
returns false.
This method operates in place, visiting each element exactly once in the original order, and preserves the order of the retained elements.
Time complexity:
- O(n) to iterate over all elements,
- O(1) to remove elements failing to satisfy the predicate.
§Examples
use orx_linked_list::*;
let mut list = List::<Doubly, _>::from_iter([0, 1, 2, 3, 4]);
list.retain(&|x| *x % 2 == 0);
assert_eq!(&[0, 2, 4], list.iter().copied().collect::<Vec<_>>().as_slice());
sourcepub fn retain_collect<Predicate, Collect>(
&mut self,
predicate: &Predicate,
collect: &mut Collect,
)
pub fn retain_collect<Predicate, Collect>( &mut self, predicate: &Predicate, collect: &mut Collect, )
O(n) Retains only the elements specified by the predicate; all elements that are removed elements are collected by the provided closure.
In other words, removes all elements e
for which predicate(&e)
returns false; and calls collect(e)
on the removed values.
This method operates in place, visiting each element exactly once in the original order, and preserves the order of the retained elements.
Time complexity:
- O(n) to iterate over all elements,
- O(1) to remove elements failing to satisfy the predicate and collect.
§Examples
use orx_linked_list::*;
let mut list = List::<Doubly, _>::from_iter([0, 1, 2, 3, 4]);
let mut odds = vec![];
let mut collect = |x| odds.push(x);
list.retain_collect(&|x| *x % 2 == 0, &mut collect);
assert_eq!(&[0, 2, 4], list.iter().copied().collect::<Vec<_>>().as_slice());
assert_eq!(&[1, 3], odds.as_slice());
Trait Implementations§
source§impl<'a, V, T> Default for List<'a, V, T>where
V: ListVariant<'a, T>,
V::Ends: ListEnds<'a, V, T>,
impl<'a, V, T> Default for List<'a, V, T>where
V: ListVariant<'a, T>,
V::Ends: ListEnds<'a, V, T>,
source§impl<'a, T, M> FromIterator<T> for List<'a, Doubly<M>, T>where
M: MemoryReclaimPolicy,
impl<'a, T, M> FromIterator<T> for List<'a, Doubly<M>, T>where
M: MemoryReclaimPolicy,
source§fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self
source§impl<'a, T, M> FromIterator<T> for List<'a, Singly<M>, T>where
M: MemoryReclaimPolicy,
impl<'a, T, M> FromIterator<T> for List<'a, Singly<M>, T>where
M: MemoryReclaimPolicy,
source§fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self
Auto Trait Implementations§
impl<'a, V, T> Freeze for List<'a, V, T>
impl<'a, V, T> RefUnwindSafe for List<'a, V, T>where
<V as Variant<'a, T>>::MemoryReclaim: RefUnwindSafe,
V: RefUnwindSafe,
<V as Variant<'a, T>>::Prev: RefUnwindSafe,
T: RefUnwindSafe,
impl<'a, V, T> Send for List<'a, V, T>
impl<'a, V, T> Sync for List<'a, V, T>
impl<'a, V, T> Unpin for List<'a, V, T>
impl<'a, V, T> UnwindSafe for List<'a, V, T>where
<V as Variant<'a, T>>::MemoryReclaim: UnwindSafe,
V: RefUnwindSafe,
<V as Variant<'a, T>>::Prev: RefUnwindSafe + UnwindSafe,
T: RefUnwindSafe + UnwindSafe,
Blanket Implementations§
source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
source§default unsafe fn clone_to_uninit(&self, dst: *mut T)
default unsafe fn clone_to_uninit(&self, dst: *mut T)
clone_to_uninit
)