cs107-lecture-examples

Example codes used during Harvard CS107 lectures
git clone https://git.0xfab.ch/cs107-lecture-examples.git
Log | Files | Refs | README | LICENSE

linked_list.py (3298B)


      1 #!/usr/bin/env python3
      2 # vim: foldmethod=marker
      3 # File       : linked_list.py
      4 # Description: Linked list example with generator function for __iter__
      5 # Copyright 2022 Harvard University. All Rights Reserved.
      6 import copy
      7 
      8 
      9 # Node {{{1
     10 class Node:
     11     def __init__(self, key, *, data=None, next=None):
     12         self.key = key
     13         self.data = data
     14         self.next = next
     15 
     16 
     17 # LinkedList {{{1
     18 class LinkedList:
     19     # List creation {{{2
     20     def __init__(self, key, data, *, reverse=False):
     21         start = Node(key[0], data=data[0])  # create root node
     22         end = start
     23         for k, d in zip(key[1:], data[1:]):
     24             if reverse:
     25                 end = self._prepend(end, Node(k, data=d))
     26             else:
     27                 end = self._append(end, Node(k, data=d))
     28         self.first = end if reverse else start
     29 
     30     @staticmethod
     31     def _append(anchor, node):
     32         anchor.next = node
     33         return node
     34 
     35     @staticmethod
     36     def _prepend(anchor, node):
     37         node.next = anchor
     38         return node
     39 
     40     # Sequence properties {{{2
     41     def __getitem__(self, key):
     42         _, node = self._getitem(key)
     43         return node
     44 
     45     def __len__(self):
     46         node = self.first
     47         count = 0
     48         while node != None:
     49             count += 1
     50             node = node.next
     51         return count
     52 
     53     def __str__(self):
     54         node = self.first
     55         pretty = ""
     56         while node != None:
     57             pretty += f"node: {hex(id(node))} : key={node.key} : data={node.data}\n"
     58             node = node.next
     59         return pretty
     60 
     61     def _getitem(self, key):
     62         """Private method to retrieve a list element given a key.
     63            Arguments:
     64               key: identifies the node
     65            Returns:
     66               Tuple with reference to predecessor node and reference to node
     67               with given key
     68         """
     69         node = self.first
     70         prev = node
     71         while node != None:
     72             if node.key == key:
     73                 return (prev, node)
     74             prev = node
     75             node = node.next
     76         raise KeyError(f"Key '{key}' not found")
     77 
     78     # Node insertion {{{2
     79     def insert(self, key, node, *, before=False):
     80         anchor = self.__getitem__(key)
     81         if before:  # insert before
     82             tmp = copy.copy(anchor)  # beware!
     83             anchor.key = node.key
     84             anchor.data = node.data
     85             node = tmp
     86             anchor.next = node
     87         else:  # insert after
     88             assert anchor is not None
     89             node.next = anchor.next
     90             anchor.next = node
     91         return node
     92 
     93     # Node removal {{{2
     94     def remove(self, key):
     95         if self.first.key == key:
     96             del_node = self.first
     97             self.first = self.first.next
     98         else:
     99             prev, del_node = self._getitem(key)
    100             prev.next = del_node.next
    101         del del_node
    102 
    103     # Iterator {{{2
    104     def __iter__(self):
    105         node = self.first
    106         while node != None:
    107             yield node
    108             node = node.next
    109 
    110 
    111 # main() {{{1
    112 def main():
    113     # create a list
    114     linked_list = LinkedList(range(5), list('abcde'))
    115 
    116     # iter(ll) returns a generator object
    117     print(type(iter(linked_list)))
    118     for node in linked_list:
    119         print(f'{node} : key={node.key} value={node.data}')
    120 
    121 
    122 if __name__ == "__main__":
    123     main()