View Source DoublyLinkedList (doubly_linked_list v0.1.0)
A fast, ammortised O(log n) doubly linked list implementation.
A doubly linked list is a type of linked list in which each node contains three elements: a data value, a pointer to the next node in the list, and a pointer to the previous node. This two-way linkage allows traversal of the list in both directions, forward and backward, which is a significant advantage over a singly linked list that can only be traversed in one direction.
A new doubly linked list can be constructed using new/0
:
iex> dll = DoublyLinkedList.new()
#DoublyLinkedList<[]>
Many types of insertion and deletion are supported, the most basic being
insert_head/2
, insert_tail/2
, remove_head/1
and remove_tail/2
which
will insert and remove at the head and tail of the doubly linked list
respectively:
iex> dll = DoublyLinkedList.new()
#DoublyLinkedList<[]>
iex> {dll, node} = DoublyLinkedList.insert_tail(dll, "tail value")
{#DoublyLinkedList<["tail value"]>, #DoublyLinkedNode<"tail value">}
iex> {dll, node} = DoublyLinkedList.insert_head(dll, "head value")
{#DoublyLinkedList<["head value", "tail value"]>, #DoublyLinkedNode<"head value">}
iex> dll = DoublyLinkedList.remove_tail(dll)
#DoublyLinkedList<["head value"]>
iex> dll = DoublyLinkedList.remove_head(dll)
#DoublyLinkedList<[]>
Node data can be updated with update/3
:
iex> dll = DoublyLinkedList.new()
#DoublyLinkedList<[]>
iex> {dll, node} = DoublyLinkedList.insert_tail(dll, "tail value")
{#DoublyLinkedList<["tail value"]>, #DoublyLinkedNode<"tail value">}
iex> dll = DoublyLinkedList.update(dll, node, "new tail value")
#DoublyLinkedList<["new tail value"]>
There are two options for traversal. DoublyLinkedList
implements the
Enumerable protocol so Enum.map/2
, Enum.member?/2
,
etc are supported; there
are also the built-in find_from_head/2
and find_from_tail/2
functions.
find_from_tail/2
is of particular interest as it traverses the list in
reverse. Note that traversal methods are O(n).
iex> dll = DoublyLinkedList.new()
iex> {dll, node} = DoublyLinkedList.insert_tail(dll, 1)
iex> {dll, node} = DoublyLinkedList.insert_tail(dll, 2)
{#DoublyLinkedList<[1, 2]>, #DoublyLinkedNode<2>}
iex> Enum.map(dll, fn v -> v * 2 end)
[2, 4]
Summary
Functions
Find the first node whose data matches the given value (starting from the head of the list).
Find the first node whose data matches the given value (starting from the tail of the list).
Get the node.
Get the node at the head of the list.
Get the node after the given node.
Get the node before the given node.
Get the node at the tail of the list.
Insert a node after the given node.
Insert a node before the given node.
Insert a node at the head of the list.
Insert a node at the tail of the list.
Construct a new list.
Remove the node.
Remove the node after the given node.
Remove the node before the given node.
Remove the node at the head of the list.
Remove the node at the tail of the list.
Update the node with the given value.
Types
@type t() :: %DoublyLinkedList{ head: String.t(), nodes: %{optional(String.t()) => DoublyLinkedList.Node.t()}, tail: String.t() }
Functions
@spec find_from_head(t(), term()) :: DoublyLinkedList.Node.t() | nil
Find the first node whose data matches the given value (starting from the head of the list).
@spec find_from_tail(t(), term()) :: DoublyLinkedList.Node.t() | nil
Find the first node whose data matches the given value (starting from the tail of the list).
@spec get(t(), String.t()) :: DoublyLinkedList.Node.t() | nil
@spec get(t(), DoublyLinkedList.Node.t()) :: DoublyLinkedList.Node.t() | nil
Get the node.
@spec get_head(t()) :: nil
@spec get_head(t()) :: DoublyLinkedList.Node.t()
Get the node at the head of the list.
@spec get_next(t(), String.t()) :: DoublyLinkedList.Node.t() | nil
@spec get_next(t(), DoublyLinkedList.Node.t()) :: DoublyLinkedList.Node.t() | nil
Get the node after the given node.
@spec get_prev(t(), String.t()) :: DoublyLinkedList.Node.t() | nil
@spec get_prev(t(), DoublyLinkedList.Node.t()) :: DoublyLinkedList.Node.t() | nil
Get the node before the given node.
@spec get_tail(t()) :: nil
@spec get_tail(t()) :: DoublyLinkedList.Node.t()
Get the node at the tail of the list.
@spec insert_after(t(), String.t(), term()) :: {t(), DoublyLinkedList.Node.t() | nil}
@spec insert_after(t(), DoublyLinkedList.Node.t(), term()) :: {t(), DoublyLinkedList.Node.t() | nil}
Insert a node after the given node.
@spec insert_before(t(), String.t(), term()) :: {t(), DoublyLinkedList.Node.t() | nil}
@spec insert_before(t(), DoublyLinkedList.Node.t(), term()) :: {t(), DoublyLinkedList.Node.t() | nil}
Insert a node before the given node.
@spec insert_head(t(), term()) :: {t(), DoublyLinkedList.Node.t()}
@spec insert_head( {t(), DoublyLinkedList.Node.t()}, term() ) :: {t(), DoublyLinkedList.Node.t()}
Insert a node at the head of the list.
@spec insert_tail(t(), term()) :: {t(), DoublyLinkedList.Node.t()}
@spec insert_tail( {t(), DoublyLinkedList.Node.t()}, term() ) :: {t(), DoublyLinkedList.Node.t()}
Insert a node at the tail of the list.
@spec new() :: t()
Construct a new list.
Remove the node.
@spec remove_after(t(), String.t()) :: t()
@spec remove_after(t(), DoublyLinkedList.Node.t()) :: t()
Remove the node after the given node.
@spec remove_before(t(), String.t()) :: t()
@spec remove_before(t(), DoublyLinkedList.Node.t()) :: t()
Remove the node before the given node.
Remove the node at the head of the list.
Remove the node at the tail of the list.
@spec update(t(), String.t(), term()) :: t() | nil
@spec update(t(), DoublyLinkedList.Node.t(), term()) :: t() | nil
Update the node with the given value.