class LinkedList_Test_Operations_On_List_with_1000_Random_Elements(unittest.TestCase): def setUp(self): self._linked_list = LinkedList() self._shadow_list = [] for i in range(10): random_element = randint(0, 1000) self._linked_list.append(random_element) self._shadow_list.append(random_element)#will keep track of count and index def test_count_index_remove_index_count_on_each_removal(self): """ Check count, index before and after each predictable removal operation """ for i in self._shadow_list[:]: self.assertEqual(self._linked_list.length, len(self._shadow_list)) self.assertEqual(self._linked_list.index(i), self._shadow_list.index(i)) self._shadow_list.remove(i) self._linked_list.remove(i) try: self._shadow_list.index(i) self.assertEqual(self._linked_list.index(i), self._shadow_list.index(i)) except ValueError: self.assertEqual(self._linked_list.index(i), -1) self.assertEqual(self._linked_list.length, len(self._shadow_list))
class LinkedList_Test_Remove_Non_Existing_Element_From_0_Element_List(unittest.TestCase): def setUp(self): self._linkedList = LinkedList() def test_count_of_list(self): self._linkedList.remove(-1) self.assertEqual(self._linkedList.length, 0, 'Length must be 0 for empty list') def tearDown(self): self._linkedList = None
class LinkedList_Test_Check_Head_On_Remove_In_4_Element_List(unittest.TestCase): def setUp(self): self._linkedList = LinkedList() self._linkedList.append(1) self._linkedList.append(2) self._linkedList.append(3) self._linkedList.append(4) def test_tail_node_on_remove(self): #list is [1, 2, 3, 4] self._linkedList.remove(3)#removed head. Head must be same node self.assertEqual(self._linkedList.head, 1) #Now list is [1, 2, 4] self._linkedList.remove(1)#head should next be 2 self.assertEqual(self._linkedList.head, 2, 'head must be adjusted on deletion of first node') #Now list is [2, 4] self._linkedList.remove(2)#head should next be 4 self.assertEqual(self._linkedList.head, 4, 'head must be adjusted on deletion of first node') #Now list is [4] self._linkedList.remove(4)#head should next be None self.assertEqual(self._linkedList.head, None, 'Head must be None on empty list') def tearDown(self): self._linkedList = None
class LinkedListHashBucket(collections.MutableMapping): ''' A hash bucket is used to hold objects that 'hash to the same value' (collision) in a hash table. This is hash a bucket using a LIST. This masquerades as a python dict in code where it is used. Note: HASHBUCKET ITERATION YIELDS KEYS. not the key value pairs in the bucket. ''' def __init__(self): self._list_of_kv_pairs = LinkedList() #we use our linked list! def __len__(self): ''' The number of entries in the bucket! ''' return self._list_of_kv_pairs.length def get(self, key, default = None): ''' Get object associated with a key and on key miss return specified default. This is there in Python dict and this class masquerades as dict, so we implement it. ''' try: value = self[key] return value except KeyError: return default def __getitem__(self, key): for kv_pair in self._list_of_kv_pairs: if kv_pair.key == key: return kv_pair.value raise KeyError('Key Error: %s ' % repr(key)) def __delitem__(self, key): for kv_pair in self._list_of_kv_pairs: if kv_pair.key == key: self._list_of_kv_pairs.remove(kv_pair) return raise KeyError('Key Error: %s ' % repr(key)) def __setitem__(self, key, obj): for kv_pair in self._list_of_kv_pairs: if kv_pair.key == key: kv_pair.value = obj return self._list_of_kv_pairs.append(KeyValuePair(key = key, value = obj)) def __iter__(self): for kvpair in self._list_of_kv_pairs: yield kvpair.key
class LinkedList_Test_Remove_Middle_Element_From_4_Element_List(unittest.TestCase): def setUp(self): self._linkedList = LinkedList() self._linkedList.append(1) self._linkedList.append(2) self._linkedList.append(3) self._linkedList.append(4) def test_count_of_list(self): self._linkedList.remove(3) self.assertEqual(self._linkedList.length, 3, 'Length not valid after trying to remove non-existin element') def tearDown(self): self._linkedList = None
class LinkedList_Test_Check_Tail_On_Remove_In_4_Element_List(unittest.TestCase): def setUp(self): self._linkedList = LinkedList() self._linkedList.append(1) self._linkedList.append(2) self._linkedList.append(3) self._linkedList.append(4) def test_tail_node_on_remove(self): self._linkedList.remove(1)#removed head. Tail must be same node self.assertEqual(self._linkedList.tail, 4) #Now list is [2, 3, 4] self._linkedList.remove(4)#tail should next be 3 self.assertEqual(self._linkedList.tail, 3, 'Tail must be adjusted on deletion of last node') #Now list is [2, 3] self._linkedList.remove(2)#tail should next be 3 self.assertEqual(self._linkedList.tail, 3, 'Tail must be adjusted on deletion of last node') #Now list is [3] self._linkedList.remove(3)#tail should next be None self.assertEqual(self._linkedList.tail, None, 'Tail must be None on empty list') def tearDown(self): self._linkedList = None
print('Tail of list is: %s' % str(link_list.tail)) print('Print list by iterating') #Find an element's index element = 4 element_index = link_list.index(element) if element_index == -1: print('Element %s was not found on list' % str(element)) else: print('Element %s found at index %s' % (str(element), str(element_index))) #Lets delete 7 print('Deleting 7') element_to_remove = 7 link_list.remove(element_to_remove) #Try to find it. print('Trying to find %s' % str(element_to_remove)) index_of_deleted = link_list.index(element_to_remove) print('Index of deleted element is %s' % str(index_of_deleted)) #print list again print_list(link_list) # #Lets insert 7 at index 5 print('Insert 7 into the list at index 4') element_to_insert = 7 index_at = 5 link_list.insert_at(index=index_at, element=element_to_insert) print_list(link_list)