Skip to content

Positional Singly Linked List

PositionalSinglyLinkedList (PositionalLinkedList, SinglyLinkedList)

A positional singly linked list is a positional list implemented based on a singly linked list

Instantiate a positional singly linked list object

>>> a_list = PositionalSinglyLinkedList()

Append an item to the list

>>> position = a_list.append(0)
>>> position.get_data()
0

The L.append(x) method is an alias of L.insert_last(x)

>>> position = a_list.insert_last(1)
>>> position.get_data()
1

Insert an item at the head of the list

>>> position = a_list.insert_first(2)
>>> position.get_data()
2

Insert an item just before a certain position in the list

>>> new_position = a_list.insert_before(position, 3)
>>> new_position.get_data()
3

Insert an item just after a certain position in the list

>>> new_position = a_list.insert_after(position, 4)
>>> new_position.get_data()
4

Replace item at a specific position

>>> a_list.replace(position, 100)
2

Check if a positional singly linked list is empty

>>> a_list.is_empty()
False
>>> PositionalSinglyLinkedList().is_empty()
True

Get first item of the list

>>> position = a_list.get_first()
>>> position.get_data()
3

Get last item of the list

>>> position = a_list.get_last()
>>> position.get_data()
1

Get item just before a certain position of the list

>>> position = a_list.get_last()
>>> before_position = a_list.get_before(position)
>>> before_position.get_data()
0

Get item just after a certain position of the list

>>> position = a_list.get_first()
>>> after_position = a_list.get_after(position)
>>> after_position.get_data()
100

Delete item just before a certain position from the list

>>> a_list.remove_before(after_position)
3

Delete item just after a certain position from the list

>>> a_list.remove_after(after_position)
4

Delete item in a certain position from the list

>>> position = a_list.get_first()
>>> a_list.remove(position)
100

Delete first item from the list

>>> a_list.remove_first()
0

Delete last item from the list

>>> a_list.remove_last()
1

get_after(self, position)

Return the position just after the passed position, None if the referenced after position doesn't exist

Parameters:

Name Type Description Default
position _Position

reference position

required

Returns:

Type Description
Optional[positional_linked_list.PositionalLinkedList._Position]

the position just after the passed position

Source code in positional_linked_lists/positional_singly_linked_list.py
def get_after(
    self, position: PositionalLinkedList._Position
) -> Union[PositionalLinkedList._Position, None]:
    super().get_after(position)

    node = position.manipulate_node(self, "_validate_node", *[])
    if node is None:
        return None

    node_to_get = node.next_node
    if isinstance(node_to_get, SinglyLinkedList._SentinelNode):
        return None
    else:
        return PositionalLinkedList._Position(self, node_to_get)

get_before(self, position)

Return the position just before the passed position, None if the referenced before position doesn't exist

Parameters:

Name Type Description Default
position _Position

reference position

required

Returns:

Type Description
Optional[positional_linked_list.PositionalLinkedList._Position]

the position just before the passed position

Source code in positional_linked_lists/positional_singly_linked_list.py
def get_before(
    self, position: PositionalLinkedList._Position
) -> Union[PositionalLinkedList._Position, None]:
    super().get_before(position)

    node = position.manipulate_node(self, "_validate_node", *[])
    if node is None:
        return None

    previous_node = self._head
    current_node = previous_node.next_node

    while current_node.data != node.data:
        previous_node = current_node
        current_node = current_node.next_node

    if isinstance(previous_node, SinglyLinkedList._SentinelNode):
        return None
    else:
        return PositionalLinkedList._Position(self, previous_node)

get_first(self)

Return the position of the item at the head of the list, None if the list is empty

Returns:

Type Description
Optional[positional_linked_list.PositionalLinkedList._Position]

the position of the item at the head of the list

Source code in positional_linked_lists/positional_singly_linked_list.py
def get_first(self) -> Union[PositionalLinkedList._Position, None]:
    if self._length == 0:
        return None

    return PositionalLinkedList._Position(self, self._head.next_node)

get_last(self)

Return the position of the item at the tail of the list, None if the list is empty

Returns:

Type Description
Optional[positional_linked_list.PositionalLinkedList._Position]

the position of the item at the tail of the list

Source code in positional_linked_lists/positional_singly_linked_list.py
def get_last(self) -> Union[PositionalLinkedList._Position, None]:
    if self._length == 0:
        return None

    current_node = self._head.next_node

    while not isinstance(current_node.next_node, SinglyLinkedList._SentinelNode):
        current_node = current_node.next_node

    return PositionalLinkedList._Position(self, current_node)

insert_after(self, position, data)

Add item after the defined position within the list

Parameters:

Name Type Description Default
position _Position

reference position

required
data Any

item to insert

required

Returns:

Type Description
_Position

the position of the added item

Source code in positional_linked_lists/positional_singly_linked_list.py
def insert_after(
    self, position: PositionalLinkedList._Position, data: Any
) -> PositionalLinkedList._Position:
    super().insert_after(position, data)

    self._length += 1
    new_node = SinglyLinkedList._Node(data)
    node = position.manipulate_node(self, "_validate_node", *[])

    SinglyLinkedList._insert_between(new_node, node, node.next_node)

    return PositionalLinkedList._Position(self, new_node)

insert_before(self, position, data)

Add item before the defined position within the list

Parameters:

Name Type Description Default
position _Position

reference position

required
data Any

item to insert

required

Returns:

Type Description
_Position

the position of the added item

Source code in positional_linked_lists/positional_singly_linked_list.py
def insert_before(
    self, position: PositionalLinkedList._Position, data: Any
) -> PositionalLinkedList._Position:
    super().insert_before(position, data)

    self._length += 1
    new_node = SinglyLinkedList._Node(data)
    node = position.manipulate_node(self, "_validate_node", *[])

    previous_node = self._head
    current_node = previous_node.next_node

    while current_node.data != node.data:
        previous_node = current_node
        current_node = current_node.next_node

    SinglyLinkedList._insert_between(new_node, previous_node, node)

    return PositionalLinkedList._Position(self, new_node)

insert_first(self, data)

Add item at the head of the list

Parameters:

Name Type Description Default
data Any

item to insert

required

Returns:

Type Description
_Position

the position of the added item

Source code in positional_linked_lists/positional_singly_linked_list.py
def insert_first(self, data: Any) -> PositionalLinkedList._Position:
    SinglyLinkedList.insert_first(self, data)
    return PositionalLinkedList._Position(self, self._head.next_node)

insert_last(self, data)

Add item at the tail of the list

Parameters:

Name Type Description Default
data Any

item to insert

required

Returns:

Type Description
_Position

the position of the added item

Source code in positional_linked_lists/positional_singly_linked_list.py
def insert_last(self, data: Any) -> PositionalLinkedList._Position:
    SinglyLinkedList.insert_last(self, data)

    current_node = self._head.next_node

    while not isinstance(current_node.next_node, SinglyLinkedList._SentinelNode):
        current_node = current_node.next_node

    return PositionalLinkedList._Position(self, current_node)

is_empty(self)

Return True if list is empty, else False

Returns:

Type Description
bool

True if list is empty, else False

Source code in positional_linked_lists/positional_singly_linked_list.py
def is_empty(self) -> bool:
    return self._length == 0

remove(self, position)

Delete item at a specific position

Parameters:

Name Type Description Default
position _Position

position containing item to be deleted

required

Returns:

Type Description
Any

the deleted item

Source code in positional_linked_lists/positional_singly_linked_list.py
def remove(self, position: PositionalLinkedList._Position) -> Any:
    super().remove(position)

    self._length -= 1
    node = position.manipulate_node(self, "_validate_node", *[])
    _ = position.manipulate_variables(self, "_invalidate_position", *[])

    previous_node = self._head
    current_node = previous_node.next_node

    while current_node.data != node.data:
        previous_node = current_node
        current_node = current_node.next_node

    SinglyLinkedList._remove_between(previous_node, node.next_node)

    return node.data

remove_after(self, position)

Delete item just after the passed position

Parameters:

Name Type Description Default
position _Position

reference position

required

Returns:

Type Description
Any

the deleted item

Source code in positional_linked_lists/positional_singly_linked_list.py
def remove_after(self, position: PositionalLinkedList._Position) -> Any:
    super().remove_after(position)

    node = position.manipulate_node(self, "_validate_node", *[])
    node_to_delete = node.next_node

    if isinstance(node_to_delete, SinglyLinkedList._SentinelNode):
        return None

    self._length -= 1
    SinglyLinkedList._remove_between(node, node_to_delete.next_node)

    return node_to_delete.data

remove_before(self, position)

Delete item just before the passed position

Parameters:

Name Type Description Default
position _Position

reference position

required

Returns:

Type Description
Any

the deleted item

Source code in positional_linked_lists/positional_singly_linked_list.py
def remove_before(self, position: PositionalLinkedList._Position) -> Any:
    super().remove_before(position)

    node = position.manipulate_node(self, "_validate_node", *[])

    pre_previous_node = None
    previous_node = self._head
    current_node = previous_node.next_node

    while current_node.data != node.data:
        pre_previous_node = previous_node
        previous_node = current_node
        current_node = current_node.next_node

    if isinstance(previous_node, SinglyLinkedList._SentinelNode):
        return None

    self._length -= 1
    SinglyLinkedList._remove_between(pre_previous_node, node)

    return previous_node.data

remove_first(self)

Delete item at the head of the list

Returns:

Type Description
Any

the deleted item

Source code in positional_linked_lists/positional_singly_linked_list.py
def remove_first(self) -> Any:
    if self._length == 0:
        return None

    node_to_delete = self._head.next_node

    SinglyLinkedList.remove_first(self)

    return node_to_delete.data

remove_last(self)

Delete item at the tail of the list

Returns:

Type Description
Any

the deleted item

Source code in positional_linked_lists/positional_singly_linked_list.py
def remove_last(self) -> Any:
    if self._length == 0:
        return None

    node_to_delete = self._head.next_node

    while not isinstance(node_to_delete.next_node, SinglyLinkedList._SentinelNode):
        node_to_delete = node_to_delete.next_node

    SinglyLinkedList.remove_last(self)

    return node_to_delete.data