use std::collections::VecDeque;
pub struct LinkList<T> {
pub nodes: VecDeque<T>, pub flags: u32, }
impl<T> Default for LinkList<T> {
fn default() -> Self {
Self::new()
}
}
impl<T> LinkList<T> {
pub fn new() -> Self { LinkList { nodes: VecDeque::new(), flags: 0 }
}
pub fn is_empty(&self) -> bool { self.nodes.is_empty()
}
pub fn len(&self) -> usize { self.nodes.len()
}
pub fn push_front(&mut self, data: T) { self.nodes.push_front(data);
}
pub fn push_back(&mut self, data: T) { self.nodes.push_back(data);
}
pub fn pop_front(&mut self) -> Option<T> { self.nodes.pop_front()
}
pub fn pop_back(&mut self) -> Option<T> { self.nodes.pop_back()
}
pub fn front(&self) -> Option<&T> {
self.nodes.front()
}
pub fn front_mut(&mut self) -> Option<&mut T> {
self.nodes.front_mut()
}
pub fn back(&self) -> Option<&T> {
self.nodes.back()
}
pub fn back_mut(&mut self) -> Option<&mut T> {
self.nodes.back_mut()
}
pub fn iter(&self) -> std::collections::vec_deque::Iter<'_, T> {
self.nodes.iter()
}
pub fn iter_mut(&mut self) -> std::collections::vec_deque::IterMut<'_, T> {
self.nodes.iter_mut()
}
pub fn append(&mut self, other: &mut LinkList<T>) { self.nodes.append(&mut other.nodes);
}
pub fn clear(&mut self) { self.nodes.clear();
}
pub fn to_vec(self) -> Vec<T>
where
T: Clone,
{
self.nodes.into_iter().collect()
}
pub fn firstnode(&self) -> Option<usize> { if self.nodes.is_empty() { None } else { Some(0) }
}
pub fn lastnode(&self) -> Option<usize> { if self.nodes.is_empty() { None } else { Some(self.nodes.len() - 1) }
}
pub fn nextnode(&self, idx: usize) -> Option<usize> { if idx + 1 < self.nodes.len() { Some(idx + 1) } else { None }
}
pub fn prevnode(&self, idx: usize) -> Option<usize> { if idx > 0 && idx <= self.nodes.len() { Some(idx - 1) } else { None }
}
pub fn getdata(&self, idx: usize) -> Option<&T> { self.nodes.get(idx)
}
pub fn setdata(&mut self, idx: usize, data: T) { if let Some(slot) = self.nodes.get_mut(idx) {
*slot = data;
}
}
pub fn empty(&self) -> bool { self.nodes.is_empty()
}
pub fn insertlinknode(&mut self, after_idx: usize, data: T) -> usize { let new_idx = after_idx + 1;
if new_idx >= self.nodes.len() {
self.nodes.push_back(data);
self.nodes.len() - 1
} else {
self.nodes.insert(new_idx, data);
new_idx
}
}
pub fn delete_node(&mut self, idx: usize) -> Option<T> { self.nodes.remove(idx)
}
pub fn insert_at(&mut self, idx: usize, data: T) {
if idx >= self.nodes.len() {
self.nodes.push_back(data);
} else {
self.nodes.insert(idx, data);
}
}
}
impl<T: Clone> Clone for LinkList<T> {
fn clone(&self) -> Self {
LinkList { nodes: self.nodes.clone(), flags: self.flags }
}
}
impl<T: std::fmt::Debug> std::fmt::Debug for LinkList<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("LinkList")
.field("nodes", &self.nodes)
.field("flags", &self.flags)
.finish()
}
}
impl<T> FromIterator<T> for LinkList<T> {
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
let mut list = LinkList::new();
for item in iter {
list.push_back(item);
}
list
}
}
impl<T> IntoIterator for LinkList<T> {
type Item = T;
type IntoIter = std::collections::vec_deque::IntoIter<T>;
fn into_iter(self) -> Self::IntoIter {
self.nodes.into_iter()
}
}
impl<'a, T> IntoIterator for &'a LinkList<T> {
type Item = &'a T;
type IntoIter = std::collections::vec_deque::Iter<'a, T>;
fn into_iter(self) -> Self::IntoIter {
self.nodes.iter()
}
}
pub fn hlinklist2array(list: &LinkList<String>) -> Vec<String> { list.iter().cloned().collect()
}
pub fn newlinklist() -> LinkList<String> { LinkList::new()
}
pub fn znewlinklist() -> LinkList<String> { LinkList::new()
}
pub fn insertlinknode<T>(list: &mut LinkList<T>, node: usize, dat: T) -> usize { list.insertlinknode(node, dat)
}
pub fn zinsertlinknode<T>(list: &mut LinkList<T>, node: usize, dat: T) -> usize {
list.insertlinknode(node, dat)
}
pub fn uinsertlinknode(list: &mut LinkList<String>, node: usize, new: String) -> Option<usize> {
if list.iter().any(|s| s == &new) {
None
} else {
Some(list.insertlinknode(node, new))
}
}
pub fn insertlinklist<T: Clone>(l: &mut LinkList<T>, after_idx: usize, x: &LinkList<T>) { let mut idx = after_idx;
for v in x.iter() {
idx = l.insertlinknode(idx, v.clone());
}
}
pub fn getlinknode<T>(list: &mut LinkList<T>) -> Option<T> { list.pop_front()
}
pub fn ugetnode<T>(list: &mut LinkList<T>) -> Option<T> { list.pop_front()
}
pub fn remnode<T>(list: &mut LinkList<T>, nd: usize) -> Option<T> { list.delete_node(nd)
}
pub fn uremnode<T>(list: &mut LinkList<T>, nd: usize) -> Option<T> { list.delete_node(nd)
}
pub fn freelinklist<T>(list: &mut LinkList<T>) { list.clear();
}
pub fn countlinknodes<T>(list: &LinkList<T>) -> usize { list.len()
}
pub fn rolllist<T>(l: &mut LinkList<T>, nd: usize) { let len = l.len();
if len > 0 {
let nd = nd % len;
for _ in 0..nd {
if let Some(v) = l.pop_front() {
l.push_back(v);
}
}
}
}
#[allow(unused_variables)]
pub fn newsizedlist<T>(size: usize) -> LinkList<T> { LinkList::new()
}
pub fn joinlists<T>(first: &mut LinkList<T>, second: &mut LinkList<T>) { first.append(second);
}
pub fn linknodebydatum<T: PartialEq>(list: &LinkList<T>, dat: &T) -> Option<usize> { list.iter().position(|v| v == dat)
}
pub fn linknodebystring(list: &LinkList<String>, dat: &str) -> Option<usize> { list.iter().position(|v| v == dat)
}
pub fn zlinklist2array(list: &LinkList<String>) -> Vec<String> { list.iter().cloned().collect()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_new_list() {
let list: LinkList<i32> = LinkList::new();
assert!(list.is_empty());
assert_eq!(list.len(), 0);
assert_eq!(list.flags, 0);
}
#[test]
fn test_push_front_back() {
let mut list = LinkList::new();
list.push_back(1);
list.push_back(2);
list.push_front(0);
assert_eq!(list.front(), Some(&0));
assert_eq!(list.back(), Some(&2));
assert_eq!(list.len(), 3);
}
#[test]
fn test_pop_front_back() {
let mut list = LinkList::new();
list.push_back(1);
list.push_back(2);
list.push_back(3);
assert_eq!(list.pop_front(), Some(1));
assert_eq!(list.pop_back(), Some(3));
assert_eq!(list.pop_front(), Some(2));
assert_eq!(list.pop_front(), None);
}
#[test]
fn test_iter() {
let mut list = LinkList::new();
list.push_back(1);
list.push_back(2);
list.push_back(3);
let v: Vec<_> = list.iter().copied().collect();
assert_eq!(v, vec![1, 2, 3]);
}
#[test]
fn test_macro_methods() {
let mut list: LinkList<String> = LinkList::new();
list.push_back("a".to_string());
list.push_back("b".to_string());
list.push_back("c".to_string());
assert_eq!(list.firstnode(), Some(0));
assert_eq!(list.lastnode(), Some(2));
assert_eq!(list.nextnode(0), Some(1));
assert_eq!(list.nextnode(2), None);
assert_eq!(list.getdata(1).map(String::as_str), Some("b"));
list.setdata(1, "B".to_string());
assert_eq!(list.getdata(1).map(String::as_str), Some("B"));
let new_idx = list.insertlinknode(1, "X".to_string());
assert_eq!(new_idx, 2);
assert_eq!(list.getdata(2).map(String::as_str), Some("X"));
assert_eq!(list.delete_node(2).as_deref(), Some("X"));
assert_eq!(list.getdata(2).map(String::as_str), Some("c"));
}
#[test]
fn test_append() {
let mut a: LinkList<i32> = vec![1, 2].into_iter().collect();
let mut b: LinkList<i32> = vec![3, 4].into_iter().collect();
a.append(&mut b);
assert!(b.is_empty());
assert_eq!(a.to_vec(), vec![1, 2, 3, 4]);
}
#[test]
fn test_clear() {
let mut list: LinkList<i32> = vec![1, 2, 3].into_iter().collect();
list.clear();
assert!(list.is_empty());
}
#[test]
fn test_uinsertlinknode_dedups() {
let mut list: LinkList<String> = LinkList::new();
list.push_back("a".to_string());
assert!(uinsertlinknode(&mut list, 0, "b".to_string()).is_some());
assert!(uinsertlinknode(&mut list, 0, "a".to_string()).is_none());
assert_eq!(list.len(), 2);
}
}