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
Exemple #6
0
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
Exemple #8
0
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()
Exemple #10
0
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)
Exemple #11
0
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)
Exemple #12
0
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)
Exemple #13
0
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
Exemple #15
0
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()
Exemple #16
0
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()
Exemple #17
0
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
Exemple #18
0
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))
Exemple #19
0
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
Exemple #20
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)