Crate cdl_list_rs

source ·
Expand description

This crate implements a Circular Doubly Linked List in Rust using Rc<T> and RefCell<T>.

Use this crate if you really like interior mutability or dislike the many unsafe blocks used in other implementations! Of course, interior mutability introduces potential runtime panics of its own, but those should not be present currently.

Usage

Create a list using cdl_list::CdlList::new():

use cdl_list_rs::cdl_list::CdlList;
 
let mut list : CdlList<u32> = CdlList::new();

The list must be mutable to add any elements to it. Elements may be added to the head or tail of the list using cdl_list::CdlList::push_front() or cdl_list::CdlList::push_back().

// Where A <══> B = A ⇄ B
list.push_front(1); // list = ╔══> 1 <══╗
                    //        ╚═════════╝
 
list.push_back(2);  // list = ╔══> 1 <══> 2 <══╗
                    //        ╚════════════════╝
 
list.push_front(3); // list = ╔══> 3 <══> 1 <══> 2 <══╗
                    //        ╚═══════════════════════╝

Additionally, you may use cdl_list::CdlList::insert_at() to insert an element into the list at a specific index.

list.insert_at(2, 4); // list = ╔══> 3 <══> 1 <══> 4 <══> 2 <══╗
                      //        ╚══════════════════════════════╝
 
assert_eq!(list.size(), 4);
assert_eq!(list.pop_back(), Some(2));
assert_eq!(list.pop_back(), Some(4));
assert_eq!(list.pop_back(), Some(1));
assert_eq!(list.pop_back(), Some(3));

To see which item is at the head or tail of the list, use cdl_list::CdlList::peek_front() or cdl_list::CdlList::peek_back(). This optionally returns a Ref<T>, which can be dereferenced using * or clone(). This creates a copy of the value and cannot modify the list’s contents!

list.push_front(1);
list.push_back(2);
list.push_front(3);
let head_val = *list.peek_front().unwrap();        // head_val = 3
let tail_val = list.peek_back().unwrap().clone();  // tail_val = 2

To remove an item from the list, you can currently use cdl_list::CdlList::pop_front() or cdl_list::CdlList::pop_back(). This gives you ownership of the value at the head or tail of the list respectively and removes it from the list, adjusting the list’s pointers appropriately. Like peek, this returns None if the list is empty.

let head = list.pop_front(); // head = Some(3)
                             // list = ╔══> 1 <══> 2 <══╗
                             //        ╚════════════════╝
 
let tail = list.pop_back();  // tail = Some(2)
                             // list = ╔══> 1 <══╗
                             //        ╚═════════╝
 
let last = list.pop_front(); // last = Some(1)
                             // list is empty
 
let empty = list.pop_back(); // empty = None

Additionally, you may use cdl_list::CdlList::remove_at() to remove an element from the list at a specific index.

list.push_front(1);
list.push_back(2);
list.push_front(3);
 
// List:  3, 1, 2
// Index: 0, 1, 2
 
assert_eq!(list.remove_at(1), Some(1));

Modules

  • A circular doubly linked list is a series of nodes where each node has a reference to the next and previous node in the list. By being circular, the head and tail of the list point to each other, making the graph cyclic. Below is an example of a small list: