dsa.singlylinkedlist API documentation

# dsa.singlylinkedlist

Module containing singly linked list class.

View Source

      1""" Module containing singly linked list class. """
      2
      3class Node:
      4    """
      5    A singly linked list node implementation.
      6    """
      7    def __init__(self, value):
      8        """
      9        A singly linked list node.
     10        Args:
     11            value: The value of the node.
     12        """
     13        #: value of the node
     14        self.value = value
     15        #: reference to the next node
     16        self.next = None
     17
     18class LinkedList:
     19    """
     20    A singly linked list implementation.
     21    """
     22    def __init__(self, head: Node=None, tail: Node=None, count: int=0):
     23        """
     24        Initialize a singly linked list.
     25
     26        if only the head node is specified, tail is set to the head node and count is automatically set to 0
     27        if both head and tail nodes are specified, count should be specified as well
     28
     29        Args:
     30            head: The reference to the head node.
     31            tail: The reference to the tail node.
     32            count: The number of nodes in the linked list.
     33
     34        """
     35        self.head = head
     36        if head and tail is None:
     37            self.tail = head
     38            self.count = 1
     39        else:
     40            self.tail = tail
     41            self.count = count
     42
     43    @classmethod
     44    def from_list(cls, mylist=None):
     45        """
     46        Create a linked list from a list.
     47
     48        Args:
     49            mylist: A list or container to convert from.
     50
     51        Returns:
     52            A  linked list containing the items from mylist.
     53        """
     54        ll = cls()
     55        for value in mylist:
     56            ll.append(value)
     57
     58        return ll
     59
     60    def to_list(self) -> list:
     61        """
     62        Create a list with contents of the linked list.
     63
     64        Returns:
     65            List with contents of linked list.
     66        """
     67        mylist = []
     68        current = self.head
     69        while current:
     70            mylist.append(current.value)
     71            current = current.next
     72        return mylist
     73
     74    def print(self):
     75        """
     76        Print the contents of the linked list.
     77        """
     78        current = self.head
     79        while current:
     80            print(current.value, end=" ")
     81            current = current.next
     82        print()
     83
     84
     85    def __repr__(self):
     86        """
     87        Return a string representation of the linked list.
     88
     89        Returns:
     90            A string representation of the linked list.
     91        """
     92        s = ""
     93        current = self.head
     94        while current:
     95            s += str(current.value) + " "
     96            current = current.next
     97
     98        return f"[ {s}] Count: {self.count}"
     99
    100    def __getitem__(self, index: int) -> Node:
    101        """
    102        Return value at a specified index. Raise IndexError if index is out of bounds.
    103
    104        Args:
    105            index: Index of value.
    106
    107        Raises:
    108            IndexError: If index is out of bounds.
    109
    110        Returns:
    111            The value at the specified index.
    112        """
    113        i = 0
    114        current = self.head
    115        while current:
    116            if i == index:
    117                return current.value
    118            current = current.next
    119            i += 1
    120        raise IndexError("Index Out of Bounds")
    121
    122    def __len__(self) -> int:
    123        """
    124        Return the number of elements in the linked list.
    125        """
    126        return self.count
    127
    128    def is_empty(self) -> bool:
    129        """
    130        Check if the linked list is empty.
    131        """
    132        return self.count == 0
    133
    134    def search(self, value) -> int:
    135        """
    136        Search for a value in the linked list.
    137
    138        Args:
    139            value: The value to search for.
    140
    141        Returns:
    142            Return index of found value.
    143
    144        Raises:
    145            Exception: If value is not found.
    146        """
    147        i = 0
    148        current = self.head
    149        while current:
    150            if current.value == value:
    151                return i
    152            i += 1
    153            current = current.next
    154        raise Exception("Value not found")
    155
    156    def insert(self, index: int, value):
    157        """
    158        Insert a value at a specified index. Raise exception if index is out of bounds.
    159
    160        Args:
    161            index (int): The index to insert a value.
    162            value: The value to append.
    163
    164        Returns:
    165            None
    166
    167        Raises:
    168            IndexError: If index is out of bounds.
    169        """
    170        i = 0
    171
    172        # insert front
    173        if index == 0:
    174            self.prepend(value)
    175            return
    176        elif index == self.count: # insert at end
    177            self.append(value)
    178            return
    179        elif index > self.count:
    180            raise IndexError("Index Out of Bounds")
    181
    182        # find node to insert after
    183        current = self.head
    184        while index < i or current:
    185            i += 1
    186            if i == index:
    187                break
    188            current = current.next
    189
    190        if index > i:
    191            raise IndexError("Index Out of Bounds")
    192
    193        new_node = Node(value)
    194        tmp = current.next
    195        current.next = new_node
    196        new_node.next = tmp
    197        self.count += 1
    198
    199    def prepend(self, value):
    200        """
    201        Place a value at the beginning of the linked list.
    202
    203        Args:
    204            value: A value to append.
    205
    206        Returns:
    207            None
    208        """
    209        new_node = Node(value)
    210        new_node.next = self.head
    211        self.head = new_node
    212        self.count += 1
    213
    214    def append(self, value):
    215        """
    216        Place a value at the end of the linked list.
    217
    218        Args:
    219            value: A value to append.
    220
    221        Returns:
    222            None
    223
    224        Raises:
    225            IndexError: If linked list is empty or index is not found.
    226        """
    227        if self.head is None:
    228            self.head = Node(value)
    229            if self.count == 0:
    230                self.tail = self.head
    231            self.count += 1
    232            return
    233
    234        # go to the end of the list
    235        new_node = Node(value)
    236        self.tail.next = new_node
    237        self.tail = new_node
    238
    239        self.count += 1
    240
    241    def delete(self, index: int):
    242        """
    243        Delete a node at a specified index. Raise IndexError if linked list is empty or if index is not found.
    244
    245        Args:
    246            index: Index of element to be deleted.
    247
    248        Returns:
    249            None
    250
    251        Raises:
    252            IndexError: If linked list is empty or index is not found.
    253        """
    254        if index == 0:
    255            self.delete_head()
    256            return
    257        elif index + 1 == self.count:
    258            self.delete_tail()
    259            return
    260
    261        i = 0
    262        current = self.head
    263        prev = None
    264        while current:
    265            if index == i:
    266                if prev is not None:
    267                    prev.next = current.next
    268                else:
    269                    self.head = current.next
    270                self.count -= 1
    271                return
    272            i += 1
    273            prev = current
    274            current = current.next
    275        raise IndexError("Index not found")
    276
    277    def delete_head(self):
    278        """
    279        Delete the head node in the linked list. Raise IndexError if linked list is empty.
    280
    281        Returns:
    282            None
    283
    284        Raises:
    285            IndexError: If linked list is empty.
    286        """
    287        if self.head is None:
    288            raise IndexError("LinkedList is Empty")
    289        self.head = self.head.next
    290        self.count -= 1
    291
    292    def delete_tail(self):
    293        """
    294        Delete the last node in the linked list. Raise IndexError if linked list is empty.
    295
    296        Returns:
    297            None
    298
    299        Raises:
    300            IndexError: If linked list is empty.
    301        """
    302        if self.head is None:
    303            raise IndexError("LinkedList is Empty")
    304
    305        if self.head.next is None:
    306            self.head = None
    307            self.count -= 1
    308            return
    309
    310        current = self.head
    311        while current.next.next:
    312            current = current.next
    313
    314        current.next = None
    315        self.tail = current
    316        self.count -= 1
    317
    318if __name__ == "__main__":
    319    ll = LinkedList.from_list(range(10))
    320    ll = LinkedList()
    321
    322    for _ in range(15):
    323        ll.append(_)
    324    assert (ll.head.value == 0)
    325    assert (ll.tail.value == 14)
    326    assert (ll.count == 15)
    327
    328    print(ll.to_list())
    329    ll.insert(1, -1)
    330    print(ll.to_list())
    331    assert (ll[1] == -1)
    332#    self.assertEqual(ll.count, 16)
    333    ll.insert(0, -2)
    334#    ll.prepend(-2)
    335    print(ll.to_list())
    336    assert (ll[0] == -2)

class Node: View Source

     4class Node:
     5    """
     6    A singly linked list node implementation.
     7    """
     8    def __init__(self, value):
     9        """
    10        A singly linked list node.
    11        Args:
    12            value: The value of the node.
    13        """
    14        #: value of the node
    15        self.value = value
    16        #: reference to the next node
    17        self.next = None

A singly linked list node implementation.

Node(value) View Source

     8    def __init__(self, value):
     9        """
    10        A singly linked list node.
    11        Args:
    12            value: The value of the node.
    13        """
    14        #: value of the node
    15        self.value = value
    16        #: reference to the next node
    17        self.next = None

A singly linked list node. Args: value: The value of the node.

value
next
class LinkedList: View Source

     19class LinkedList:
     20    """
     21    A singly linked list implementation.
     22    """
     23    def __init__(self, head: Node=None, tail: Node=None, count: int=0):
     24        """
     25        Initialize a singly linked list.
     26
     27        if only the head node is specified, tail is set to the head node and count is automatically set to 0
     28        if both head and tail nodes are specified, count should be specified as well
     29
     30        Args:
     31            head: The reference to the head node.
     32            tail: The reference to the tail node.
     33            count: The number of nodes in the linked list.
     34
     35        """
     36        self.head = head
     37        if head and tail is None:
     38            self.tail = head
     39            self.count = 1
     40        else:
     41            self.tail = tail
     42            self.count = count
     43
     44    @classmethod
     45    def from_list(cls, mylist=None):
     46        """
     47        Create a linked list from a list.
     48
     49        Args:
     50            mylist: A list or container to convert from.
     51
     52        Returns:
     53            A  linked list containing the items from mylist.
     54        """
     55        ll = cls()
     56        for value in mylist:
     57            ll.append(value)
     58
     59        return ll
     60
     61    def to_list(self) -> list:
     62        """
     63        Create a list with contents of the linked list.
     64
     65        Returns:
     66            List with contents of linked list.
     67        """
     68        mylist = []
     69        current = self.head
     70        while current:
     71            mylist.append(current.value)
     72            current = current.next
     73        return mylist
     74
     75    def print(self):
     76        """
     77        Print the contents of the linked list.
     78        """
     79        current = self.head
     80        while current:
     81            print(current.value, end=" ")
     82            current = current.next
     83        print()
     84
     85
     86    def __repr__(self):
     87        """
     88        Return a string representation of the linked list.
     89
     90        Returns:
     91            A string representation of the linked list.
     92        """
     93        s = ""
     94        current = self.head
     95        while current:
     96            s += str(current.value) + " "
     97            current = current.next
     98
     99        return f"[ {s}] Count: {self.count}"
    100
    101    def __getitem__(self, index: int) -> Node:
    102        """
    103        Return value at a specified index. Raise IndexError if index is out of bounds.
    104
    105        Args:
    106            index: Index of value.
    107
    108        Raises:
    109            IndexError: If index is out of bounds.
    110
    111        Returns:
    112            The value at the specified index.
    113        """
    114        i = 0
    115        current = self.head
    116        while current:
    117            if i == index:
    118                return current.value
    119            current = current.next
    120            i += 1
    121        raise IndexError("Index Out of Bounds")
    122
    123    def __len__(self) -> int:
    124        """
    125        Return the number of elements in the linked list.
    126        """
    127        return self.count
    128
    129    def is_empty(self) -> bool:
    130        """
    131        Check if the linked list is empty.
    132        """
    133        return self.count == 0
    134
    135    def search(self, value) -> int:
    136        """
    137        Search for a value in the linked list.
    138
    139        Args:
    140            value: The value to search for.
    141
    142        Returns:
    143            Return index of found value.
    144
    145        Raises:
    146            Exception: If value is not found.
    147        """
    148        i = 0
    149        current = self.head
    150        while current:
    151            if current.value == value:
    152                return i
    153            i += 1
    154            current = current.next
    155        raise Exception("Value not found")
    156
    157    def insert(self, index: int, value):
    158        """
    159        Insert a value at a specified index. Raise exception if index is out of bounds.
    160
    161        Args:
    162            index (int): The index to insert a value.
    163            value: The value to append.
    164
    165        Returns:
    166            None
    167
    168        Raises:
    169            IndexError: If index is out of bounds.
    170        """
    171        i = 0
    172
    173        # insert front
    174        if index == 0:
    175            self.prepend(value)
    176            return
    177        elif index == self.count: # insert at end
    178            self.append(value)
    179            return
    180        elif index > self.count:
    181            raise IndexError("Index Out of Bounds")
    182
    183        # find node to insert after
    184        current = self.head
    185        while index < i or current:
    186            i += 1
    187            if i == index:
    188                break
    189            current = current.next
    190
    191        if index > i:
    192            raise IndexError("Index Out of Bounds")
    193
    194        new_node = Node(value)
    195        tmp = current.next
    196        current.next = new_node
    197        new_node.next = tmp
    198        self.count += 1
    199
    200    def prepend(self, value):
    201        """
    202        Place a value at the beginning of the linked list.
    203
    204        Args:
    205            value: A value to append.
    206
    207        Returns:
    208            None
    209        """
    210        new_node = Node(value)
    211        new_node.next = self.head
    212        self.head = new_node
    213        self.count += 1
    214
    215    def append(self, value):
    216        """
    217        Place a value at the end of the linked list.
    218
    219        Args:
    220            value: A value to append.
    221
    222        Returns:
    223            None
    224
    225        Raises:
    226            IndexError: If linked list is empty or index is not found.
    227        """
    228        if self.head is None:
    229            self.head = Node(value)
    230            if self.count == 0:
    231                self.tail = self.head
    232            self.count += 1
    233            return
    234
    235        # go to the end of the list
    236        new_node = Node(value)
    237        self.tail.next = new_node
    238        self.tail = new_node
    239
    240        self.count += 1
    241
    242    def delete(self, index: int):
    243        """
    244        Delete a node at a specified index. Raise IndexError if linked list is empty or if index is not found.
    245
    246        Args:
    247            index: Index of element to be deleted.
    248
    249        Returns:
    250            None
    251
    252        Raises:
    253            IndexError: If linked list is empty or index is not found.
    254        """
    255        if index == 0:
    256            self.delete_head()
    257            return
    258        elif index + 1 == self.count:
    259            self.delete_tail()
    260            return
    261
    262        i = 0
    263        current = self.head
    264        prev = None
    265        while current:
    266            if index == i:
    267                if prev is not None:
    268                    prev.next = current.next
    269                else:
    270                    self.head = current.next
    271                self.count -= 1
    272                return
    273            i += 1
    274            prev = current
    275            current = current.next
    276        raise IndexError("Index not found")
    277
    278    def delete_head(self):
    279        """
    280        Delete the head node in the linked list. Raise IndexError if linked list is empty.
    281
    282        Returns:
    283            None
    284
    285        Raises:
    286            IndexError: If linked list is empty.
    287        """
    288        if self.head is None:
    289            raise IndexError("LinkedList is Empty")
    290        self.head = self.head.next
    291        self.count -= 1
    292
    293    def delete_tail(self):
    294        """
    295        Delete the last node in the linked list. Raise IndexError if linked list is empty.
    296
    297        Returns:
    298            None
    299
    300        Raises:
    301            IndexError: If linked list is empty.
    302        """
    303        if self.head is None:
    304            raise IndexError("LinkedList is Empty")
    305
    306        if self.head.next is None:
    307            self.head = None
    308            self.count -= 1
    309            return
    310
    311        current = self.head
    312        while current.next.next:
    313            current = current.next
    314
    315        current.next = None
    316        self.tail = current
    317        self.count -= 1

A singly linked list implementation.

LinkedList( head: Node = None, tail: Node = None, count: int = 0) View Source

    23    def __init__(self, head: Node=None, tail: Node=None, count: int=0):
    24        """
    25        Initialize a singly linked list.
    26
    27        if only the head node is specified, tail is set to the head node and count is automatically set to 0
    28        if both head and tail nodes are specified, count should be specified as well
    29
    30        Args:
    31            head: The reference to the head node.
    32            tail: The reference to the tail node.
    33            count: The number of nodes in the linked list.
    34
    35        """
    36        self.head = head
    37        if head and tail is None:
    38            self.tail = head
    39            self.count = 1
    40        else:
    41            self.tail = tail
    42            self.count = count

Initialize a singly linked list.

if only the head node is specified, tail is set to the head node and count is automatically set to 0 if both head and tail nodes are specified, count should be specified as well

Args: head: The reference to the head node. tail: The reference to the tail node. count: The number of nodes in the linked list.

head
@classmethod
def from_list(cls, mylist=None): View Source

    44    @classmethod
    45    def from_list(cls, mylist=None):
    46        """
    47        Create a linked list from a list.
    48
    49        Args:
    50            mylist: A list or container to convert from.
    51
    52        Returns:
    53            A  linked list containing the items from mylist.
    54        """
    55        ll = cls()
    56        for value in mylist:
    57            ll.append(value)
    58
    59        return ll

Create a linked list from a list.

Args: mylist: A list or container to convert from.

Returns: A linked list containing the items from mylist.

def to_list(self) -> list: View Source

    61    def to_list(self) -> list:
    62        """
    63        Create a list with contents of the linked list.
    64
    65        Returns:
    66            List with contents of linked list.
    67        """
    68        mylist = []
    69        current = self.head
    70        while current:
    71            mylist.append(current.value)
    72            current = current.next
    73        return mylist

Create a list with contents of the linked list.

Returns: List with contents of linked list.

def print(self): View Source

    75    def print(self):
    76        """
    77        Print the contents of the linked list.
    78        """
    79        current = self.head
    80        while current:
    81            print(current.value, end=" ")
    82            current = current.next
    83        print()

Print the contents of the linked list.

def is_empty(self) -> bool: View Source

    129    def is_empty(self) -> bool:
    130        """
    131        Check if the linked list is empty.
    132        """
    133        return self.count == 0

Check if the linked list is empty.

def search(self, value) -> int: View Source

    135    def search(self, value) -> int:
    136        """
    137        Search for a value in the linked list.
    138
    139        Args:
    140            value: The value to search for.
    141
    142        Returns:
    143            Return index of found value.
    144
    145        Raises:
    146            Exception: If value is not found.
    147        """
    148        i = 0
    149        current = self.head
    150        while current:
    151            if current.value == value:
    152                return i
    153            i += 1
    154            current = current.next
    155        raise Exception("Value not found")

Search for a value in the linked list.

Args: value: The value to search for.

Returns: Return index of found value.

Raises: Exception: If value is not found.

def insert(self, index: int, value): View Source

    157    def insert(self, index: int, value):
    158        """
    159        Insert a value at a specified index. Raise exception if index is out of bounds.
    160
    161        Args:
    162            index (int): The index to insert a value.
    163            value: The value to append.
    164
    165        Returns:
    166            None
    167
    168        Raises:
    169            IndexError: If index is out of bounds.
    170        """
    171        i = 0
    172
    173        # insert front
    174        if index == 0:
    175            self.prepend(value)
    176            return
    177        elif index == self.count: # insert at end
    178            self.append(value)
    179            return
    180        elif index > self.count:
    181            raise IndexError("Index Out of Bounds")
    182
    183        # find node to insert after
    184        current = self.head
    185        while index < i or current:
    186            i += 1
    187            if i == index:
    188                break
    189            current = current.next
    190
    191        if index > i:
    192            raise IndexError("Index Out of Bounds")
    193
    194        new_node = Node(value)
    195        tmp = current.next
    196        current.next = new_node
    197        new_node.next = tmp
    198        self.count += 1

Insert a value at a specified index. Raise exception if index is out of bounds.

Args: index (int): The index to insert a value. value: The value to append.

Returns: None

Raises: IndexError: If index is out of bounds.

def prepend(self, value): View Source

    200    def prepend(self, value):
    201        """
    202        Place a value at the beginning of the linked list.
    203
    204        Args:
    205            value: A value to append.
    206
    207        Returns:
    208            None
    209        """
    210        new_node = Node(value)
    211        new_node.next = self.head
    212        self.head = new_node
    213        self.count += 1

Place a value at the beginning of the linked list.

Args: value: A value to append.

Returns: None

def append(self, value): View Source

    215    def append(self, value):
    216        """
    217        Place a value at the end of the linked list.
    218
    219        Args:
    220            value: A value to append.
    221
    222        Returns:
    223            None
    224
    225        Raises:
    226            IndexError: If linked list is empty or index is not found.
    227        """
    228        if self.head is None:
    229            self.head = Node(value)
    230            if self.count == 0:
    231                self.tail = self.head
    232            self.count += 1
    233            return
    234
    235        # go to the end of the list
    236        new_node = Node(value)
    237        self.tail.next = new_node
    238        self.tail = new_node
    239
    240        self.count += 1

Place a value at the end of the linked list.

Args: value: A value to append.

Returns: None

Raises: IndexError: If linked list is empty or index is not found.

def delete(self, index: int): View Source

    242    def delete(self, index: int):
    243        """
    244        Delete a node at a specified index. Raise IndexError if linked list is empty or if index is not found.
    245
    246        Args:
    247            index: Index of element to be deleted.
    248
    249        Returns:
    250            None
    251
    252        Raises:
    253            IndexError: If linked list is empty or index is not found.
    254        """
    255        if index == 0:
    256            self.delete_head()
    257            return
    258        elif index + 1 == self.count:
    259            self.delete_tail()
    260            return
    261
    262        i = 0
    263        current = self.head
    264        prev = None
    265        while current:
    266            if index == i:
    267                if prev is not None:
    268                    prev.next = current.next
    269                else:
    270                    self.head = current.next
    271                self.count -= 1
    272                return
    273            i += 1
    274            prev = current
    275            current = current.next
    276        raise IndexError("Index not found")

Delete a node at a specified index. Raise IndexError if linked list is empty or if index is not found.

Args: index: Index of element to be deleted.

Returns: None

Raises: IndexError: If linked list is empty or index is not found.

def delete_head(self): View Source

    278    def delete_head(self):
    279        """
    280        Delete the head node in the linked list. Raise IndexError if linked list is empty.
    281
    282        Returns:
    283            None
    284
    285        Raises:
    286            IndexError: If linked list is empty.
    287        """
    288        if self.head is None:
    289            raise IndexError("LinkedList is Empty")
    290        self.head = self.head.next
    291        self.count -= 1

Delete the head node in the linked list. Raise IndexError if linked list is empty.

Returns: None

Raises: IndexError: If linked list is empty.

def delete_tail(self): View Source

    293    def delete_tail(self):
    294        """
    295        Delete the last node in the linked list. Raise IndexError if linked list is empty.
    296
    297        Returns:
    298            None
    299
    300        Raises:
    301            IndexError: If linked list is empty.
    302        """
    303        if self.head is None:
    304            raise IndexError("LinkedList is Empty")
    305
    306        if self.head.next is None:
    307            self.head = None
    308            self.count -= 1
    309            return
    310
    311        current = self.head
    312        while current.next.next:
    313            current = current.next
    314
    315        current.next = None
    316        self.tail = current
    317        self.count -= 1

Delete the last node in the linked list. Raise IndexError if linked list is empty.

Returns: None

Raises: IndexError: If linked list is empty.