use std::ptr;
pub struct SinglyLinkedList<T> {
root: *mut Node<T>,
leaf: *mut Node<T>,
pub size: u32,
}
impl<T: PartialEq> SinglyLinkedList<T> {
pub fn new(data: T) -> SinglyLinkedList<T> {
let root = Node::new_mut(data);
SinglyLinkedList {
root,
leaf: root,
size: 1,
}
}
pub fn new_empty() -> SinglyLinkedList<T> {
SinglyLinkedList {
root: ptr::null_mut(),
leaf: ptr::null_mut(),
size: 0,
}
}
pub fn push(&mut self, data: T) {
if self.leaf.is_null() {
self.root = Node::new_mut(data);
self.leaf = self.root;
} else {
unsafe {
if !(*self.leaf).next.is_null() {
return;
}
(*self.leaf).next = Node::new_mut(data);
self.leaf = (*self.leaf).next;
}
}
self.size += 1;
}
pub fn insert(&mut self, data: T) {
self.root = Node::new_mut_with_next(data, self.root);
if self.leaf.is_null() {
self.leaf = self.root;
}
self.size += 1;
}
pub fn pop(&mut self) {
if self.leaf == self.root {
unsafe {
drop(Box::from_raw(self.root));
self.root = ptr::null_mut();
self.leaf = ptr::null_mut();
self.size = 0;
return;
}
}
let mut current = self.root;
unsafe {
while !(*(*current).next).next.is_null() {
current = (*current).next;
}
drop(Box::from_raw((*current).next));
(*current).next = ptr::null_mut();
self.leaf = current;
self.size -= 1;
}
}
pub fn remove_first(&mut self) {
if self.size == 0 {
return;
}
if self.leaf == self.root {
unsafe {
drop(Box::from_raw(self.root));
self.root = ptr::null_mut();
self.leaf = ptr::null_mut();
self.size = 0;
return;
}
}
unsafe {
let new_root = (*self.root).next;
drop(Box::from_raw(self.root));
self.root = ptr::null_mut();
self.root = new_root;
self.size -= 1;
}
}
pub fn remove_data(&mut self, data: T) {
unsafe {
if (*self.root).data == data {
self.remove_first();
return;
} else if (*self.leaf).data == data {
self.pop();
return;
}
let mut past = self.root;
let mut current = (*self.root).next;
while (*current).data != data {
if (*current).next.is_null() {
return;
}
past = current;
current = (*current).next;
}
drop(Box::from_raw((*past).next));
(*past).next = (*current).next;
}
}
pub fn remove_at(&mut self, index: u32) {
if self.size == 0 {
return;
} else {
if index == 0 {
self.remove_first();
return;
} else if index == self.size - 1 {
self.pop();
return;
}
let mut current = self.root;
let mut pos: u32 = 0;
unsafe {
while !(*current).next.is_null() && pos < index {
if pos == index - 1 {
drop(Box::from_raw((*current).next));
(*current).next = (*(*current).next).next;
self.size -= 1;
return;
} else {
current = (*current).next;
pos += 1;
}
}
}
}
}
pub fn get_first(&self) -> Option<&T> {
if self.root.is_null() {
None
} else {
unsafe { Some(&(*self.root).data) }
}
}
pub fn get_last(&self) -> Option<&T> {
if self.leaf.is_null() {
None
} else {
unsafe { Some(&(*self.leaf).data) }
}
}
pub fn get(&self, index: u32) -> Option<&T> {
if self.size == 0 {
None
} else if index == self.size - 1 {
self.get_last()
} else if index == 0 {
self.get_first()
} else {
let mut current = self.root;
let mut pos: u32 = 0;
unsafe {
while !(*current).next.is_null() && pos < index {
current = (*current).next;
pos += 1;
}
if pos != index {
None
} else {
Some(&(*current).data)
}
}
}
}
}
struct Node<T> {
data: T,
next: *mut Node<T>,
}
impl<T> Node<T> {
fn new(data: T) -> Node<T> {
Node {
data,
next: ptr::null_mut(),
}
}
fn new_with_next(data: T, next: *mut Node<T>) -> Node<T> {
Node { data, next }
}
fn new_mut(data: T) -> *mut Node<T> {
Box::into_raw(Box::new(Self::new(data)))
}
fn new_mut_with_next(data: T, next: *mut Node<T>) -> *mut Node<T> {
Box::into_raw(Box::new(Self::new_with_next(data, next)))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn find_first() {
let list = SinglyLinkedList::new(10);
assert_eq!(list.get_first(), Some(&10));
assert_eq!(list.get_last(), Some(&10));
assert_eq!(list.size, 1);
}
#[test]
fn find_inserted() {
let mut list = SinglyLinkedList::new(10);
list.insert(1);
assert_eq!(list.get_first(), Some(&1));
assert_eq!(list.get_last(), Some(&10));
assert_eq!(list.size, 2);
}
#[test]
fn find_last() {
let mut list = SinglyLinkedList::new(10);
list.push(20);
assert_eq!(list.get_first(), Some(&10));
assert_eq!(list.get_last(), Some(&20));
assert_eq!(list.size, 2)
}
#[test]
fn find_at() {
let mut list = SinglyLinkedList::new(10);
list.push(20);
list.push(30);
list.push(40);
assert_eq!(list.get(0), Some(&10));
assert_eq!(list.get(1), Some(&20));
assert_eq!(list.get(2), Some(&30));
assert_eq!(list.get(3), Some(&40));
}
#[test]
fn find_removed() {
let mut list = SinglyLinkedList::new(10);
list.push(20);
list.push(30);
list.push(40);
list.push(50);
list.remove_first();
assert_eq!(list.get_first(), Some(&20));
assert_eq!(list.get(1), Some(&30));
assert_eq!(list.size, 4);
list.pop();
assert_eq!(list.get_last(), Some(&40));
assert_eq!(list.get(list.size - 2), Some(&30));
assert_eq!(list.size, 3);
list.remove_at(1);
assert_eq!(list.get_first(), Some(&20));
assert_eq!(list.get_last(), Some(&40));
assert_eq!(list.get(1), Some(&40));
assert_eq!(list.size, 2);
list.remove_data(20);
assert_eq!(list.get_first(), Some(&40));
assert_eq!(list.get_last(), Some(&40));
assert_eq!(list.size, 1);
list.remove_first();
assert_eq!(list.get_first(), None);
assert_eq!(list.get_last(), None);
assert_eq!(list.size, 0);
}
#[test]
fn find_first_empty_list() {
let mut list = SinglyLinkedList::<i32>::new_empty();
assert_eq!(list.size, 0);
assert_eq!(list.get_first(), None);
assert_eq!(list.get_last(), None);
list.push(10);
assert_eq!(list.size, 1);
assert_eq!(list.get_first(), Some(&10));
assert_eq!(list.get_last(), Some(&10));
list.remove_first();
list.insert(20);
assert_eq!(list.get_first(), Some(&20));
assert_eq!(list.get_last(), Some(&20));
assert_eq!(list.size, 1);
}
}