Exemplo n.º 1
0
    def test_prepend(self):

        linked_list = LinkedList()
        linked_list.prepend(1)
        linked_list.prepend(2)

        assert linked_list.to_array() == [2, 1]
Exemplo n.º 2
0
    def test_prepend(self):

        linked_list = LinkedList()
        linked_list.prepend(1)
        linked_list.prepend(2)

        assert linked_list.to_array() == [2, 1]
Exemplo n.º 3
0
    def consolidate(self):
        """
        Restructure the tree back to a binomial tree
        """
        trees_by_rank = {}
        tree_stack = Stack()

        for tree in self.trees:
            tree_stack.push(tree)

        # Iterate over the trees and merge trees of the same rank
        while not tree_stack.is_empty():
            tree = tree_stack.pop()

            if tree is None:
                continue

            if tree.rank in trees_by_rank:
                existing_tree = trees_by_rank[tree.rank]
                del trees_by_rank[tree.rank]
                tree_stack.push(tree.merge_min(existing_tree))

            else:
                trees_by_rank[tree.rank] = tree

        # Build a new tree list and find the new min node
        new_trees = trees_by_rank.values()
        self.trees = LinkedList()
        self.min_tree = None

        for new_tree in new_trees:
            self.trees.append(new_tree)
            if self.min_tree is None or self.min_tree.value.value > new_tree.value:
                self.min_tree = self.trees.get_tail_node()
Exemplo n.º 4
0
    def test_exercise_4(self):
        linked_list_a = LinkedList.from_array([1, 2, 3])
        linked_list_b = LinkedList.from_array([3, 2, 1])
        linked_list_c = LinkedList.from_array([0, 0, 7, 1])

        assert (linked_list_a + linked_list_b).to_array() == [4, 4, 4]

        assert (linked_list_a + linked_list_c).to_array() == [1, 2, 0, 2]
Exemplo n.º 5
0
    def test_exercise_4(self):
        linked_list_a = LinkedList.from_array([1, 2, 3])
        linked_list_b = LinkedList.from_array([3, 2, 1])
        linked_list_c = LinkedList.from_array([0, 0, 7, 1])

        assert (linked_list_a + linked_list_b).to_array() == [4, 4, 4]

        assert (linked_list_a + linked_list_c).to_array() == [1, 2, 0, 2]
Exemplo n.º 6
0
    def test_exercise_1(self):
        assert LinkedList.from_array([]).remove_duplicates().to_array() == []

        assert LinkedList.from_array([1, 1, 1, 1, 1, 1
                                      ]).remove_duplicates().to_array() == [1]

        assert LinkedList.from_array(
            [1, 3, 4, 6, 2, 3,
             1]).remove_duplicates().to_array() == [1, 3, 4, 6, 2]
Exemplo n.º 7
0
    def __init__(self, data=None):
        if not data:
            data = []

        self.trees = LinkedList()

        self.min_tree = None

        for i in data:
            self.insert(i)
Exemplo n.º 8
0
    def test_exercise_5(self):
        linked_list = LinkedList.from_array([1, 2, 3, 4, 5])

        assert linked_list.find_loop() is None

        # Insert a circular dependency 5 -> 2
        linked_list.get_tail_node().set_next_node(linked_list.head.get_next_node())

        assert linked_list.find_loop().value == 2

        empty_linked_list = LinkedList.from_array([])

        assert_raises(IndexError, empty_linked_list.get_tail_node)
Exemplo n.º 9
0
    def test_exercise_2(self):
        assert list(
            LinkedList.from_array(
                [1, 2, 3, 4, 5, 6,
                 7]).get_nth_to_last(0)) == [1, 2, 3, 4, 5, 6, 7]

        assert list(
            LinkedList.from_array([1, 2, 3, 4, 5, 6,
                                   7]).get_nth_to_last(5)) == [6, 7]

        assert_raises(
            IndexError, lambda x: list(
                LinkedList.from_array([1, 2, 3, 4, 5, 6, 7]).get_nth_to_last(x)
            ), 7)
Exemplo n.º 10
0
    def test_exercise_5(self):
        linked_list = LinkedList.from_array([1, 2, 3, 4, 5])

        assert linked_list.find_loop() is None

        # Insert a circular dependency 5 -> 2
        linked_list.get_tail_node().set_next_node(
            linked_list.head.get_next_node())

        assert linked_list.find_loop().value == 2

        empty_linked_list = LinkedList.from_array([])

        assert_raises(IndexError, empty_linked_list.get_tail_node)
Exemplo n.º 11
0
    def consolidate(self):
        """
        Restructure the tree back to a binomial tree
        """
        trees_by_rank = {}
        tree_stack = Stack()

        for tree in self.trees:
            tree_stack.push(tree)

        # Iterate over the trees and merge trees of the same rank
        while not tree_stack.is_empty():
            tree = tree_stack.pop()

            if tree is None:
                continue

            if tree.rank in trees_by_rank:
                existing_tree = trees_by_rank[tree.rank]
                del trees_by_rank[tree.rank]
                tree_stack.push(tree.merge_min(existing_tree))

            else:
                trees_by_rank[tree.rank] = tree

        # Build a new tree list and find the new min node
        new_trees = trees_by_rank.values()
        self.trees = LinkedList()
        self.min_tree = None

        for new_tree in new_trees:
            self.trees.append(new_tree)
            if self.min_tree is None or self.min_tree.value.value > new_tree.value:
                self.min_tree = self.trees.get_tail_node()
Exemplo n.º 12
0
    def test_linked_list_get(self):
        ll = LinkedList.from_array([1, 2, 3, 4])

        assert ll.get(3).value == 4

        assert ll.get(0).value == 1

        assert len(ll) == 4

        assert_raises(IndexError, ll.get, 4)
Exemplo n.º 13
0
    def __init__(self, data=None):
        if not data:
            data = []

        self.trees = LinkedList()

        self.min_tree = None

        for i in data:
            self.insert(i)
Exemplo n.º 14
0
    def test_linked_list_insert(self):
        ll = LinkedList.from_array([1, 2, 3])

        ll.insert(0, 4)

        assert ll.to_array() == [4, 1, 2, 3]
        assert len(ll) == 4

        ll.insert(4, 10)

        assert ll.to_array() == [4, 1, 2, 3, 10]
        assert len(ll) == 5
Exemplo n.º 15
0
    def test_linked_list_remove(self):
        ll = LinkedList.from_array([2, 3, 4, 5, 6])

        assert len(ll) == 5

        ll.remove(0)

        assert ll.to_array() == [3, 4, 5, 6]
        assert len(ll) == 4

        ll.remove(3)

        assert ll.to_array() == [3, 4, 5]
        assert len(ll) == 3

        assert_raises(IndexError, ll.remove, 3)
Exemplo n.º 16
0
class FibonacciHeap(object):
    def __init__(self, data=None):
        if not data:
            data = []

        self.trees = LinkedList()

        self.min_tree = None

        for i in data:
            self.insert(i)

    def insert(self, value):
        tree = BinomialTreeNode(value)
        tree.marked = False

        self.trees.append(tree)

        # Update the min node reference if needed
        if self.min_tree is None or self.min_tree.value.value > value:
            self.min_tree = self.trees.get_tail_node()

    def pop(self):
        """
        Remove the minimum node from the heap
        Actual cost. O(rank(H)) + O(trees(H))
        * O(rank(H)) to meld min's children into root list.
        * O(rank(H)) + O(trees(H)) to update min.
        * O(rank(H)) + O(trees(H)) to consolidate trees.
        """
        if not self.min_tree:
            raise IndexError()
        value = self.min_tree.value.value

        for child in self.min_tree.value.children:
            self.trees.append(child)

        self.min_tree.value = None
        self.min_tree = None

        self.consolidate()

        return value

    def merge(self, heap: 'FibonacciHeap'):
        if len(self.trees) == 0:
            self.trees = heap.trees

        self.trees.merge(heap.trees)
        if heap.min_tree and (
                self.min_tree is None
                or heap.min_tree.value.value < self.min_tree.value.value):
            self.min_tree = heap.min_tree

    def decrease_min(self, node: BinomialTreeNode, value):
        if node.value < value:
            raise ValueError('Value should be smaller than this value')

        parent = node.parent

        while parent:

            # Remove node from parent and add it to the tree list
            parent.children.remove(node)
            node.parent = None
            self.trees.append(node)
            node.marked = False

            if self.min_tree is None or self.min_tree.value > node.value:
                self.min_tree = self.trees.get_tail_node()

            # Mark the parent
            if parent.marked:
                pass
                # Todo: finish decrease min

    # Utility functions
    def consolidate(self):
        """
        Restructure the tree back to a binomial tree
        """
        trees_by_rank = {}
        tree_stack = Stack()

        for tree in self.trees:
            tree_stack.push(tree)

        # Iterate over the trees and merge trees of the same rank
        while not tree_stack.is_empty():
            tree = tree_stack.pop()

            if tree is None:
                continue

            if tree.rank in trees_by_rank:
                existing_tree = trees_by_rank[tree.rank]
                del trees_by_rank[tree.rank]
                tree_stack.push(tree.merge_min(existing_tree))

            else:
                trees_by_rank[tree.rank] = tree

        # Build a new tree list and find the new min node
        new_trees = trees_by_rank.values()
        self.trees = LinkedList()
        self.min_tree = None

        for new_tree in new_trees:
            self.trees.append(new_tree)
            if self.min_tree is None or self.min_tree.value.value > new_tree.value:
                self.min_tree = self.trees.get_tail_node()

    def number_of_trees(self):
        return len(self.trees)

    def get_max_rank(self):
        if self.trees.get(0):
            return max(map(lambda x: x.rank, self.trees))

    def __find_min_tree(self) -> LinkedListNode:
        """
        Find the binomial subtree with the minimal element
        """
        node = self.trees.head

        current_min = None

        while node:
            if node.value and node.value.value:
                if current_min and current_min.value:
                    current_min = node if current_min.value.value > node.value.value else current_min
                else:
                    current_min = node
            node = node.get_next_node()
        return current_min

    def __len__(self):
        return sum(map(lambda x: len(x) if x else 0, self.trees))

    def is_empty(self):
        return self.min_tree is None
Exemplo n.º 17
0
class FibonacciHeap(object):

    def __init__(self, data=None):
        if not data:
            data = []

        self.trees = LinkedList()

        self.min_tree = None

        for i in data:
            self.insert(i)

    def insert(self, value):
        tree = BinomialTreeNode(value)
        tree.marked = False

        self.trees.append(tree)

        # Update the min node reference if needed
        if self.min_tree is None or self.min_tree.value.value > value:
            self.min_tree = self.trees.get_tail_node()

    def pop(self):
        """
        Remove the minimum node from the heap
        Actual cost. O(rank(H)) + O(trees(H))
        * O(rank(H)) to meld min's children into root list.
        * O(rank(H)) + O(trees(H)) to update min.
        * O(rank(H)) + O(trees(H)) to consolidate trees.
        """
        if not self.min_tree:
            raise IndexError()
        value = self.min_tree.value.value

        for child in self.min_tree.value.children:
            self.trees.append(child)

        self.min_tree.value = None
        self.min_tree = None

        self.consolidate()

        return value

    def merge(self, heap: 'FibonacciHeap'):
        if len(self.trees) == 0:
            self.trees = heap.trees

        self.trees.merge(heap.trees)
        if heap.min_tree and (self.min_tree is None or heap.min_tree.value.value < self.min_tree.value.value):
            self.min_tree = heap.min_tree

    def decrease_min(self, node: BinomialTreeNode, value):
        if node.value < value:
            raise ValueError('Value should be smaller than this value')

        parent = node.parent

        while parent:

            # Remove node from parent and add it to the tree list
            parent.children.remove(node)
            node.parent = None
            self.trees.append(node)
            node.marked = False

            if self.min_tree is None or self.min_tree.value > node.value:
                self.min_tree = self.trees.get_tail_node()

            # Mark the parent
            if parent.marked:
                pass
                # Todo: finish decrease min

    # Utility functions
    def consolidate(self):
        """
        Restructure the tree back to a binomial tree
        """
        trees_by_rank = {}
        tree_stack = Stack()

        for tree in self.trees:
            tree_stack.push(tree)

        # Iterate over the trees and merge trees of the same rank
        while not tree_stack.is_empty():
            tree = tree_stack.pop()

            if tree is None:
                continue

            if tree.rank in trees_by_rank:
                existing_tree = trees_by_rank[tree.rank]
                del trees_by_rank[tree.rank]
                tree_stack.push(tree.merge_min(existing_tree))

            else:
                trees_by_rank[tree.rank] = tree

        # Build a new tree list and find the new min node
        new_trees = trees_by_rank.values()
        self.trees = LinkedList()
        self.min_tree = None

        for new_tree in new_trees:
            self.trees.append(new_tree)
            if self.min_tree is None or self.min_tree.value.value > new_tree.value:
                self.min_tree = self.trees.get_tail_node()

    def number_of_trees(self):
        return len(self.trees)

    def get_max_rank(self):
        if self.trees.get(0):
            return max(map(lambda x: x.rank, self.trees))

    def __find_min_tree(self) -> LinkedListNode:
        """
        Find the binomial subtree with the minimal element
        """
        node = self.trees.head

        current_min = None

        while node:
            if node.value and node.value.value:
                if current_min and current_min.value:
                    current_min = node if current_min.value.value > node.value.value else current_min
                else:
                    current_min = node
            node = node.get_next_node()
        return current_min

    def __len__(self):
        return sum(map(lambda x: len(x) if x else 0, self.trees))

    def is_empty(self):
        return self.min_tree is None
Exemplo n.º 18
0
    def test_exercise_1(self):
        assert LinkedList.from_array([]).remove_duplicates().to_array() == []

        assert LinkedList.from_array([1, 1, 1, 1, 1, 1]).remove_duplicates().to_array() == [1]

        assert LinkedList.from_array([1, 3, 4, 6, 2, 3, 1]).remove_duplicates().to_array() == [1, 3, 4, 6, 2]
Exemplo n.º 19
0
    def test_linked_list_iter(self):
        ll = LinkedList.from_array([1, 2, 3])

        assert list(ll) == [1, 2, 3]
Exemplo n.º 20
0
    def test_linked_list_reverse(self):
        ll = LinkedList.from_array([1, 2, 3])

        ll.reverse()

        assert ll.to_array() == [3, 2, 1]
Exemplo n.º 21
0
    def test_exercise_2(self):
        assert list(LinkedList.from_array([1, 2, 3, 4, 5, 6, 7]).get_nth_to_last(0)) == [1, 2, 3, 4, 5, 6, 7]

        assert list(LinkedList.from_array([1, 2, 3, 4, 5, 6, 7]).get_nth_to_last(5)) == [6, 7]

        assert_raises(IndexError, lambda x: list(LinkedList.from_array([1, 2, 3, 4, 5, 6, 7]).get_nth_to_last(x)), 7)