def test_list_with_one_element(helper): val = helper.get_value() dl = DoublyLinkedList() dl.insert(0, val) assert dl._head.get_data() == val assert dl._tail.get_data() == val assert dl._head.get_next() is None assert dl._head.get_prev() is None assert dl._tail.get_next() is None assert dl._tail.get_prev() is None assert len(dl) == 1 assert not dl.is_empty() assert val in dl assert [item for item in dl] == [val] assert dl.to_list() == [val] assert dl == dl.copy() assert dl == dl.reverse() # ==================== test rotate ==================== assert dl == dl.rotate_left(helper.get_pos_int(), inplace=False) assert dl == dl.rotate_right(helper.get_pos_int(), inplace=False) # ==================== test operators ==================== assert dl != DoublyLinkedList() assert dl > DoublyLinkedList() assert dl >= DoublyLinkedList() assert DoublyLinkedList() < dl assert DoublyLinkedList() <= dl with pytest.raises(TypeError): assert dl != LinkedList() with pytest.raises(TypeError): assert dl > LinkedList() with pytest.raises(TypeError): assert dl >= LinkedList() with pytest.raises(TypeError): assert LinkedList() < dl with pytest.raises(TypeError): assert LinkedList() <= dl # ==================== test add/remove ==================== new_value = helper.get_value() dl.add_front(new_value) dl.remove_front() dl.add_end(new_value) dl.remove_end() tmp_dl = DoublyLinkedList() tmp_dl.add_front(val) assert dl == tmp_dl # ==================== test insert/split ==================== with pytest.raises(IndexError): dl.insert(2, helper.get_value()) with pytest.raises(IndexError): dl.insert(-1, helper.get_value()) with pytest.raises(IndexError): dl.split(helper.get_pos_int(a=2))
def test_creating_doubly_linked_list_from_iterable(helper): # Using from_iterable (small length) lst = helper.get_list() dl = DoublyLinkedList(lst) assert dl._head.get_data() == lst[0] assert dl._tail.get_data() == lst[-1] assert len(dl) == dl._length == len(lst) assert dl.to_list() == [item for item in dl] == lst # Using from_iterable (has None) with pytest.raises(ValueError): DoublyLinkedList([1, 2, None, 3]) with pytest.raises(TypeError): DoublyLinkedList().add_end(LinkedList()) with pytest.raises(TypeError): DoublyLinkedList().add_front(DoublyLinkedList()) # Using from_iterable (big length) lst = helper.get_list(length=10000) dl = DoublyLinkedList(lst) assert dl._head.get_data() == lst[0] assert dl._tail.get_data() == lst[-1] assert len(dl) == dl._length == len(lst) assert dl.to_list() == [item for item in dl] == lst for _ in range(100): # check random indices idx = helper.get_pos_int(b=10000 - 1) assert dl[idx] == lst[idx] # Using Linked List lst = helper.get_list() tmp_dl = DoublyLinkedList(lst) dl = DoublyLinkedList(tmp_dl) assert dl == tmp_dl assert len(dl) == dl._length == len(lst) assert dl.to_list() == [item for item in dl] == lst
def test_not_empty_doubly_node(helper): val = helper.get_value() node = DoublyNode(val) assert node.get_data() == val assert node.get_next() is None assert node.get_prev() is None node.set_next(None) node.set_prev(None) with pytest.raises(ValueError): DoublyNode(None) with pytest.raises(ValueError): node.set_data(None) with pytest.raises(ValueError): node.set_next(Node(None)) with pytest.raises(ValueError): node.set_prev(Node(None)) node.set_next(DoublyNode(helper.get_value())) # do nothing node.set_prev(DoublyNode(helper.get_value())) # do nothing # Given value: has __iter__ attribute lst = helper.get_list() node = DoublyNode(lst) assert node.get_data() == lst assert node.get_next() is None assert node.get_prev() is None node.set_next(DoublyNode(helper.get_string())) node.set_prev(DoublyNode(helper.get_string())) # Given value: LinkedList() dl = LinkedList(helper.get_list()) with pytest.raises(TypeError): DoublyNode(dl) # Given value: LinkedList() dl = DoublyLinkedList(helper.get_list()) with pytest.raises(TypeError): DoublyNode(dl)
def test_extend_method(helper): lst = helper.get_list() # two Doubly linked lists are empty dllist1 = DoublyLinkedList() dllist1.extend(DoublyLinkedList()) assert dllist1 == DoublyLinkedList() # one linked list is empty dllist1 = DoublyLinkedList([]) dllist2 = DoublyLinkedList(lst) dllist1.extend(dllist2) assert dllist1 == dllist2 assert len(dllist1) == len(lst) dllist2.extend(dllist1) assert len(dllist2) == 2 * len(lst) # two linked lists are NOT empty dllist1 = DoublyLinkedList(lst) dllist2 = DoublyLinkedList(lst) dllist2.extend(dllist1) assert dllist1.to_list() == lst assert dllist2.to_list() == lst + lst assert len(dllist2) == 2 * len(lst) # extend other data type with pytest.raises(TypeError): DoublyLinkedList().extend(LinkedList()) with pytest.raises(TypeError): DoublyLinkedList().extend(helper.get_list()) with pytest.raises(TypeError): DoublyLinkedList().extend(helper.get_value())
def test_creating_circular_linked_list_from_iterable(helper): # Using from_iterable (small length) lst = helper.get_list() cll = CircularLinkedList(lst) assert cll._head.get_data() == lst[0] assert len(cll) == cll._length == len(lst) assert cll.to_list() == [item for item in cll] == lst # Using from_iterable (has None) with pytest.raises(ValueError): CircularLinkedList([1, 2, None, 3]) with pytest.raises(TypeError): CircularLinkedList().add_end(LinkedList()) with pytest.raises(TypeError): CircularLinkedList().add_front(DoublyLinkedList()) with pytest.raises(TypeError): CircularLinkedList().add_front(CircularLinkedList()) # Using from_iterable (big length) lst = helper.get_list(length=10000) cll = CircularLinkedList(lst) assert cll._head.get_data() == lst[0] assert len(cll) == cll._length == len(lst) assert cll.to_list() == [item for item in cll] == lst for _ in range(100): # check random indices idx = helper.get_pos_int(b=10000 - 1) assert cll[idx] == lst[idx] # Using Linked List lst = helper.get_list() tmp_cll = CircularLinkedList(lst) cll = CircularLinkedList(tmp_cll) # assert cll == tmp_cll assert len(cll) == cll._length == len(lst) assert cll.to_list() == [item for item in cll] == lst
def test_creating_linked_list_from_constructor(helper): # Using constructor val = helper.get_value() ll = LinkedList() ll.add_front(val) assert isinstance(ll._head, Node) assert ll._head.get_data() == val assert ll._head.get_next() == ll._head._next is None assert len(ll) == ll._length == 1 assert ll.to_list() == [item for item in ll] == [val] # Using Node val = helper.get_value() ll = LinkedList() ll.add_end(val) assert isinstance(ll._head, Node) ll._head.get_data() == val ll._head.get_next() == ll._head._next is None assert len(ll) == ll._length == 1 assert ll.to_list() == [item for item in ll] == [val]
def _add_extra_level(self): """ Creates a new level at the top of the `SkipList()`, a new level is a new `LinkedList()` instance attached to the `SkipList()`. Returns ------- LinkedList(): The newly-created `LinkedList()` instance after being attached to the other `LinkedList()` object in the lower level. """ top_list = self._level_lists[self._num_levels - 1] new_llist = LinkedList() new_llist._insert_node(new_llist._head, self._basic_node(float("-inf"))) # connect the head of the new linked list to the lower linked list new_llist._head.set_down(top_list._head) # add new linked list to the SkipList self._level_lists.append(new_llist) self._num_levels += 1 return new_llist
def test_split_method(helper): lst = helper.get_list(length=100) ll = LinkedList(lst) for i in range(len(lst)): # test left list left_list, right_list = ll.split(i) assert isinstance(left_list, LinkedList) assert left_list.to_list() == lst[:i] assert left_list.copy().to_list() == lst[:i] assert left_list.reverse().to_list() == lst[:i][::-1] # test right list assert isinstance(right_list, LinkedList) assert right_list.to_list() == lst[i:] assert right_list.copy().to_list() == lst[i:] assert right_list.reverse().to_list() == lst[i:][::-1] ll.add_front(0) ll.add_end("apple") assert ll._length == len(ll) == len(lst) + 2 assert ll.to_list() == [0] + lst + ["apple"]
def test_circular_linked_list_with_known_values(): cll = CircularLinkedList() cll.add_front(10) cll.add_front(5) assert cll.to_list() == [5, 10] cll.remove(20) cll.remove_front() assert cll == CircularLinkedList([10]) cll.remove_end() assert cll == CircularLinkedList() cll.insert(0, 100) cll.insert(1, 200) cll.insert(1, 100) assert 100 in cll and 200 in cll assert cll == CircularLinkedList([100, 100, 200]) assert cll.copy().to_list() == [100, 100, 200] assert cll.reverse() == CircularLinkedList([200, 100, 100]) cll.remove(100) rev = cll.reverse() assert cll == rev == CircularLinkedList([200]) cll.clear() assert not rev.is_empty() assert cll.is_empty() # ================================================== cll = LinkedList() cll.add_front(6) cll.add_end(20) cll.insert(1, 10) cll.insert(2, 77) cll.insert(4, 43) cll.insert(0, 2) assert 43 in cll assert cll[1:4].to_list() == [6, 10, 77] assert cll.copy().to_list() == [2, 6, 10, 77, 20, 43] del cll[len(cll) - 1] assert cll.reverse().to_list() == [20, 77, 10, 6, 2] assert cll._length == len(cll) == 5 cll.clear() assert cll.is_empty()
def test_not_empty_node(helper): # Given value: str s = helper.get_string() node = Node(s) assert node.get_data() == node._data == s assert node.get_data() != s.upper() assert node.get_next() == node._next is None with pytest.raises(ValueError): node.set_data(None) with pytest.raises(TypeError): node.set_next(helper.get_string()) with pytest.raises(TypeError): node.set_next(helper.get_value()) # Given value: has __iter__ attribute lst = helper.get_list() node = Node(lst) assert node.get_data() == lst assert node.get_next() is None node.set_next(Node(helper.get_string())) # Given value: LinkedList() ll = LinkedList(helper.get_list()) with pytest.raises(TypeError): Node(ll)
def test_rotate(): # rotate when inplace = False ll = LinkedList([1, 2, 3, 4, 5, 6]) rotated = ll.rotate_right(1, inplace=False) assert rotated.to_list() == [6, 1, 2, 3, 4, 5] assert isinstance(rotated._head, Node) assert rotated._head.get_data() == 6 assert rotated[4] == 4 rotated = ll.rotate_left(3, inplace=False) assert isinstance(rotated._head, Node) assert rotated.to_list() == [4, 5, 6, 1, 2, 3] assert rotated._head.get_data() == 4 assert rotated[-1] == 3 assert ll.to_list() == [1, 2, 3, 4, 5, 6] # rotate when inplace = True ll.rotate_right(1) assert ll.to_list() == [6, 1, 2, 3, 4, 5] assert isinstance(ll._head, Node) assert ll._head.get_data() == 6 ll.rotate_left(3) assert ll.to_list() == [3, 4, 5, 6, 1, 2] assert ll._head.get_data() == 3 assert isinstance(ll._head, Node)
def test_extend_method(helper): lst = helper.get_list() # two linked lists are empty llist1 = LinkedList() llist1.extend(LinkedList()) assert llist1 == LinkedList() # one linked list is empty llist1 = LinkedList([]) llist2 = LinkedList(lst) llist1.extend(llist2) assert llist1 == llist2 assert len(llist1) == len(lst) llist2.extend(llist1) assert len(llist2) == 2 * len(lst) # two linked lists are NOT empty llist1 = LinkedList(lst) llist2 = LinkedList(lst) llist2.extend(llist1) assert llist1.to_list() == lst assert llist2.to_list() == lst + lst assert len(llist2) == 2 * len(lst)
def test_relational_operators(helper): # linked lists have just one value assert LinkedList([3.14]) == LinkedList([3.14]) assert LinkedList([helper.get_int()]) != LinkedList([helper.get_float()]) assert LinkedList([helper.get_string()]) != LinkedList([helper.get_int()]) assert LinkedList([helper.get_float()]) != LinkedList([helper.get_list()]) assert LinkedList([2.9999]) < LinkedList([3]) assert LinkedList([3.14]) <= LinkedList([3.14]) assert LinkedList([3, 2]) > LinkedList([3]) assert LinkedList(["3.14"]) >= LinkedList(["3.14"]) with pytest.raises(TypeError): LinkedList([helper.get_float()]) < LinkedList([helper.get_string()]) with pytest.raises(TypeError): LinkedList([helper.get_value()]) <= LinkedList([helper.get_list()]) with pytest.raises(TypeError): LinkedList([helper.get_string()]) > LinkedList([helper.get_list()]) with pytest.raises(TypeError): LinkedList([helper.get_list()]) >= LinkedList([helper.get_float()]) # linked lists have more than one value llist1 = LinkedList([1, "2", 3.14]) llist2 = LinkedList([1, "2", 5.14]) assert llist1 == llist1 assert llist1 != llist2 assert llist1 < llist2 assert llist1 <= llist2 assert llist2 > llist1 assert llist2 >= llist2 # slicing lists assert llist1[:-1] == llist2[:-1] assert llist1[-1:] != llist2[-1:] assert llist1[:1] < llist2 assert llist1[:2] <= llist2 with pytest.raises(TypeError): assert llist1[1:] < llist2 with pytest.raises(TypeError): assert llist1[1:] <= llist2 # if the other one isn't a linked list actual_list = [1, "2", 5.14] with pytest.raises(TypeError): assert llist1 == actual_list with pytest.raises(TypeError): assert llist1 != actual_list with pytest.raises(TypeError): assert llist1 < actual_list with pytest.raises(TypeError): assert llist1 <= actual_list with pytest.raises(TypeError): assert llist2 > actual_list with pytest.raises(TypeError): assert llist2 >= actual_list
def test_relational_operators(helper): # linked lists have just one value assert DoublyLinkedList([3.14]) == DoublyLinkedList([3.14]) assert ( DoublyLinkedList([helper.get_int()]) != DoublyLinkedList([helper.get_float()]) ) assert ( DoublyLinkedList([helper.get_string()]) != DoublyLinkedList([helper.get_int()]) ) assert ( DoublyLinkedList([helper.get_float()]) != DoublyLinkedList([helper.get_list()]) ) assert DoublyLinkedList([2.9999]) < DoublyLinkedList([3]) assert DoublyLinkedList([3.14]) <= DoublyLinkedList([3.14]) assert DoublyLinkedList([3, 2]) > DoublyLinkedList([3]) assert DoublyLinkedList(["3.14"]) >= DoublyLinkedList(["3.14"]) with pytest.raises(TypeError): ( DoublyLinkedList([helper.get_float()]) < DoublyLinkedList([helper.get_string()]) ) with pytest.raises(TypeError): ( DoublyLinkedList([helper.get_value()]) <= DoublyLinkedList([helper.get_list()]) ) with pytest.raises(TypeError): ( DoublyLinkedList([helper.get_string()]) > DoublyLinkedList([helper.get_list()]) ) with pytest.raises(TypeError): ( DoublyLinkedList([helper.get_list()]) >= DoublyLinkedList([helper.get_float()]) ) # linked lists have more than one value dllist1 = DoublyLinkedList([1, "2", 3.14]) dllist2 = DoublyLinkedList([1, "2", 5.14]) assert dllist1 == dllist1 assert dllist1 != dllist2 assert dllist1 < dllist2 assert dllist1 <= dllist2 assert dllist2 > dllist1 assert dllist2 >= dllist1 # slicing lists assert dllist1[:-1] == dllist2[:-1] assert dllist1[-1:] != dllist2[-1:] assert dllist1[:1] < dllist2 assert dllist1[:2] <= dllist2 with pytest.raises(TypeError): assert dllist1[1:] < dllist2 with pytest.raises(TypeError): assert dllist1[1:] <= dllist2 # if the other one isn't a doubly linked list actual_list = [1, "2", 5.14] with pytest.raises(TypeError): assert dllist1 == actual_list with pytest.raises(TypeError): assert dllist1 != actual_list with pytest.raises(TypeError): assert dllist1 < actual_list with pytest.raises(TypeError): assert dllist1 <= actual_list with pytest.raises(TypeError): assert dllist2 > actual_list with pytest.raises(TypeError): assert dllist2 >= actual_list # if the other one is a linked list llist = LinkedList([1, "2", 5.14]) with pytest.raises(TypeError): assert dllist1 == llist with pytest.raises(TypeError): assert dllist1 != llist with pytest.raises(TypeError): assert dllist1 < llist with pytest.raises(TypeError): assert dllist1 <= llist with pytest.raises(TypeError): assert dllist2 > llist with pytest.raises(TypeError): assert dllist2 >= llist
def test_list_with_random_numbers(helper): # test add_end() and remove_end() lst = helper.get_list(length=100) llist = LinkedList() for i in lst: llist.add_end(i) assert len(llist) == len(lst) assert llist._head.get_data() == lst[0] assert not llist.is_empty() for _ in range(len(lst)): assert llist[0] == lst[0] lst.pop() llist.remove_end() assert len(llist) == 0 assert llist.is_empty() # test add_front() and remove_front() lst = helper.get_list(length=100) for i in lst: llist.add_front(i) assert len(llist) == len(lst) assert llist._head.get_data() == lst[-1] assert not llist.is_empty() for _ in range(len(lst)): assert llist[0] == lst[-1] lst.pop() llist.remove_front() assert len(llist) == 0 assert llist.is_empty()
def test_list_with_known_values(): ll = LinkedList() ll.add_front(10) ll.add_front(5) assert ll.to_list() == [5, 10] ll.remove(20) ll.remove_front() assert ll == LinkedList([10]) ll.remove_end() assert ll == LinkedList() ll.insert(0, 100) ll.insert(1, 200) ll.insert(1, 100) assert 100 in ll and 200 in ll assert ll == LinkedList([100, 100, 200]) assert ll.copy().to_list() == [100, 100, 200] assert ll.reverse() == LinkedList([200, 100, 100]) ll.remove(100) rev = ll.reverse() assert ll == rev == LinkedList([200]) ll.clear() assert not rev.is_empty() assert ll.is_empty() # ======================================== ll = LinkedList() ll.add_front(6) ll.add_end(20) ll.insert(1, 10) ll.insert(2, 77) ll.insert(4, 43) ll.insert(0, 2) assert 43 in ll assert ll[1:4].to_list() == [6, 10, 77] assert ll.copy().to_list() == [2, 6, 10, 77, 20, 43] del ll[len(ll) - 1] assert ll.reverse().to_list() == [20, 77, 10, 6, 2] assert ll._length == len(ll) == 5 ll.clear() assert ll.is_empty()
def test_creating_linked_list_from_iterable(helper): # Using from_iterable (small length) lst = helper.get_list() ll = LinkedList(lst) assert isinstance(ll._head, Node) assert ll._head.get_data() == lst[0] assert len(ll) == ll._length == len(lst) assert ll.to_list() == [item for item in ll] == lst # Using from_iterable (has None) with pytest.raises(ValueError): LinkedList([1, 2, None, 3]) with pytest.raises(TypeError): LinkedList().add_end(LinkedList()) # Using from_iterable (big length) lst = helper.get_list(length=10000) ll = LinkedList(lst) assert isinstance(ll._head, Node) assert ll._head.get_data() == lst[0] assert len(ll) == ll._length == len(lst) assert ll.to_list() == [item for item in ll] == lst for _ in range(100): # check random indices idx = helper.get_pos_int(b=10000 - 1) assert ll[idx] == lst[idx] # iterable is Linked List lst = helper.get_list() tmp_ll = LinkedList(lst) ll = LinkedList(tmp_ll) assert ll == tmp_ll assert ll._head.get_data() == tmp_ll._head.get_data() assert len(ll) == ll._length == len(lst) assert ll.to_list() == [item for item in ll] == lst
def test_list_with_one_element(helper): val = helper.get_value() ll = LinkedList() ll.insert(0, val) assert isinstance(ll._head, Node) assert ll._head.get_data() == val assert ll._head.get_next() is None assert len(ll) == 1 assert not ll.is_empty() assert val in ll assert [item for item in ll] == [val] assert ll.to_list() == [val] assert ll == ll.copy() assert ll == ll.reverse() # ==================== test rotate ==================== assert ll == ll.rotate_left(helper.get_pos_int(), inplace=False) assert ll == ll.rotate_right(helper.get_pos_int(), inplace=False) # ==================== test operators ==================== assert ll != LinkedList() assert ll > LinkedList() assert ll >= LinkedList() assert LinkedList() < ll assert LinkedList() <= ll # ==================== test add/remove ==================== new_value = helper.get_value() ll.add_front(new_value) ll.remove_front() ll.add_end(new_value) ll.remove_end() assert ll == LinkedList([val]) # ==================== test insert/split ==================== with pytest.raises(IndexError): ll.insert(2, helper.get_value()) with pytest.raises(IndexError): ll.insert(-1, helper.get_value()) with pytest.raises(IndexError): ll.split(helper.get_pos_int(a=2))
def test_list_with_same_value(helper): length = helper.get_pos_int() val = helper.get_value() ll = LinkedList() # test add_end for _ in range(length): ll.add_end(val) # test add_front for _ in range(length): ll.add_front(val) # test __setitem__() ll[1] = val assert ll == ll.reverse() assert ll == ll.copy() assert not ll.is_empty() assert len(ll) == 2 * length assert ll.count(val) == 2 * length assert ll.to_list() == [val] * (2 * length) # test split left_list, right_list = ll.split(length) assert len(left_list) == len(right_list) == length # test clear left_list.clear() right_list.clear() assert len(left_list) == len(right_list) == 0 # test remove for i in range(length): if i > length // 2: ll.remove_end() else: ll.remove_front() assert len(ll) == ll.count(val) == length ll.remove(val, all=True) assert ll.is_empty() assert len(ll) == 0
def test_empty_linked_list(helper): EMPTY = "┌─\n│\n└─" # represents empty LinkedList ll = LinkedList([]) assert str(ll) == EMPTY assert ll._length == len(ll) == 0 assert ll.is_empty() assert ll.to_list() == [] assert [_ for _ in ll] == [] assert len(ll.copy()) == 0 assert len(ll.reverse()) == 0 # =================== test operators ==================== assert LinkedList() == LinkedList() assert ll == ll.copy() assert ll == ll.reverse() assert LinkedList() != LinkedList([helper.get_value()]) assert LinkedList() < LinkedList([helper.get_value()]) assert LinkedList() <= LinkedList([helper.get_value()]) assert LinkedList([helper.get_value()]) > LinkedList() assert LinkedList([helper.get_value()]) >= LinkedList() # ==================== test count ==================== assert ll.count(0) == 0 assert ll.count(None) == 0 assert ll.count(helper.get_value()) == 0 assert ll.count(Node(helper.get_value())) == 0 # ==================== test __contains__ =================== assert None not in ll assert Node(helper.get_value()) not in ll assert 0 not in ll assert helper.get_value() not in ll assert LinkedList() not in ll # ==================== test split ==================== left_list, right_list = ll.split(0) assert str(left_list) == str(right_list) == EMPTY with pytest.raises(TypeError): ll.split(helper.get_string()) with pytest.raises(TypeError): ll.split(helper.get_float()) with pytest.raises(TypeError): ll.split(True) with pytest.raises(IndexError): ll.split(-1) with pytest.raises(IndexError): ll.split(helper.get_int()) # ==================== test rotate ==================== assert ll.rotate_left(helper.get_pos_int(), inplace=False) == ll assert ll.rotate_right(helper.get_pos_int(), inplace=False) == ll assert len(ll.rotate_left(helper.get_pos_int(), inplace=False)) == 0 assert len(ll.rotate_right(helper.get_pos_int(), inplace=False)) == 0 with pytest.raises(TypeError): ll.rotate_left(helper.get_string()) with pytest.raises(TypeError): ll.rotate_right(helper.get_float()) with pytest.raises(TypeError): ll.rotate_left([]) with pytest.raises(ValueError): ll.rotate_left(helper.get_neg_int()) with pytest.raises(ValueError): ll.rotate_right(helper.get_neg_int()) # ==================== test remove/del ==================== ll.remove_front() # shouldn't raise any Error ll.remove_end() # shouldn't raise any Error ll.remove(helper.get_value()) ll.remove(helper.get_value(), False) with pytest.raises(TypeError): ll.remove(helper.get_value(), all=helper.get_string(1)) with pytest.raises(IndexError): del ll[0] with pytest.raises(IndexError): del ll[helper.get_pos_int()] with pytest.raises(IndexError): del ll[helper.get_neg_int()] # ==================== test __getitem__ ==================== with pytest.raises(IndexError): _ = ll[0] with pytest.raises(IndexError): _ = ll[helper.get_pos_int()] with pytest.raises(IndexError): _ = ll[helper.get_neg_int()] assert LinkedList() == ll[0:10] # ==================== test insert/set ==================== with pytest.raises(IndexError): ll.insert(helper.get_pos_int(), helper.get_value()) with pytest.raises(IndexError): ll.insert(helper.get_neg_int(), helper.get_value()) with pytest.raises(IndexError): ll[0] = helper.get_float() with pytest.raises(IndexError): ll[helper.get_int()] = Node(helper.get_float()) with pytest.raises(ValueError): ll.insert(0, None)
def __init__(self, iterable=None): """ Initializes a `SkipList()` instance using an optional iterable object in time-complexity of O(n) where **n** is the number of elements inside the given `iterable`. Parameters ---------- iterable: iterable, optional An iterable python object that implements the `__iter__` method. For example, `list` and `tuple` are both iterables. Raises ------ TypeError: It can be raised in three cases 1. In case the given object isn't iterable. 2. If one of the elements in the iterable is an `Extra` object. 3. If one of the elements in the iterable is NOT a number. ValueError: If one of the iterable elements is `None`. Note ----- Inserting values into different levels in the skip list is completely random. So, running the following example will return different values each time you run it. So, in order to obtain the same result as before you need to set `random.seed(1)` before running any of the previous example. Examples -------- >>> import random; random.seed(1) >>> sl = SkipList([10, -5, 7, 9]) >>> sl ┌────┐ ┌────┐ | -∞ │⟶⟶⟶⟶⟶⟶⟶⟶⟶⟶⟶⟶⟶⟶⟶⟶⟶⟶⟶⟶| 10 │⟶ ├────┤ ┌────┐ ├────┤ | -∞ │⟶| -5 │⟶⟶⟶⟶⟶⟶⟶⟶⟶⟶⟶⟶⟶| 10 │⟶ ├────┤ ├────┤ ┌───┐ ┌───┐ ├────┤ | -∞ │⟶| -5 │⟶| 7 │⟶| 9 │⟶| 10 │⟶ └────┘ └────┘ └───┘ └───┘ └────┘ Using an iterable object with `None` as one of its elements will raise `ValueError` >>> sl = SkipList([2, None]) ValueError: Can't use `None` as an element within `extra.SkipList()`!! Using a non-iterable object will raise `TypeError` >>> sl = SkipList(2) TypeError: The given object isn't iterable!! Using nested `SkipList` objects will raise `TypeError` as well >>> sl_1 = SkipList([1]) >>> sl_2 = SkipList([1, sl_1]) TypeError: Can't create `extra.SkipList()` using `extra.SkipList()`!! """ # NOTE: `_level_lists` is an array of LinkedList() objects if iterable is None: ll = LinkedList() ll._insert_node(ll._head, self._basic_node(float("-inf"))) self._level_lists = [ll] self._num_levels = 1 elif not hasattr(iterable, "__iter__"): raise TypeError("The given object isn't iterable!!") elif isinstance(iterable, self.__class__): self._level_lists = iterable._level_lists self._num_levels = iterable._num_levels else: ll = LinkedList() ll._insert_node(ll._head, self._basic_node(float("-inf"))) self._level_lists = [ll] self._num_levels = 1 for item in iterable: self.insert(item)