Exemplo n.º 1
0
 def floor(self, key: Key):
     r = self.rank(key)
     if r >= len(self._items):
         return self.max()
     if r == 0 and not eq(self._items[r].key, key):
         return None
     return self._items[r].key if eq(self._items[r].key,
                                     key) else self._items[r - 1].key
Exemplo n.º 2
0
    def delete(self, key):
        # no node with the given key exists in the tree
        if self.get(key) is None:
            return

        parent = None
        is_node_left_child = False
        node = self._root
        while node is not None:
            if eq(key, node.key):
                break

            parent = node
            # this is why we want to make sure that the key must exist in the tree.
            parent.node_count = parent.node_count - 1

            if lt(key, node.key):
                node = node.left
                is_node_left_child = True
            else:
                node = node.right
                is_node_left_child = False

        successor, parent_of_successor = self._find_successor_and_parent(node)

        if successor is None:  # the deleted node has no right subtree
            if parent is None:  # the deleted node is the current root
                self._root = node.left
            elif is_node_left_child:
                parent.left = node.left
            else:
                parent.right = node.left
        else:
            # replace successor by its right child
            # Note: Because the successor is the left-most node, it can either have no child or only one right child,
            # and it must be its parent's left child.
            if parent_of_successor is not None:
                parent_of_successor.left = successor.right

            # replace the deleted node by its successor
            if parent is None:  # the deleted node is the current root
                self._root = successor
            elif is_node_left_child:
                parent.left = successor
            else:
                parent.right = successor

            successor.left = node.left
            # the successor is the node's right child if it is the only node in the node's right subtree,
            # and we want to avoid cycle here.
            if not eq(successor, node.right):
                successor.right = node.right

        if successor is not None:
            successor.node_count = node.node_count - 1
        if parent_of_successor is not None:
            parent_of_successor.node_count = parent_of_successor.node_count - 1
Exemplo n.º 3
0
 def ceiling(self, key: Key):
     r = self.rank(key)
     if r >= len(self._items):
         return None
     if r == 0 and not eq(self._items[r].key, key):
         return self.min()
     return self._items[r].key
Exemplo n.º 4
0
 def _rank(self, key, node):
     if node is None:
         return 0
     left_child_count = node.left.node_count if node.left is not None else 0
     if eq(key, node.key):
         return left_child_count
     if gt(key, node.key):
         return 1 + left_child_count + self._rank(key, node.right)
     return self._rank(key, node.left)
Exemplo n.º 5
0
    def put(self, key: Key, value):
        r = self.rank(key)

        if r >= len(self._items):
            self._items.append(KeyValue(key, value))
        elif eq(self._items[r].key, key):
            self._items[r].value = value
        else:
            shift_right(self._items, r)
            self._items[r] = KeyValue(key, value)
Exemplo n.º 6
0
    def get(self, key) -> Optional[Node]:
        if self.is_empty():
            return None

        current = self._root
        while current is not None:
            if eq(current.key, key):
                return current
            current = current.left if lt(key, current.key) else current.right
        return None
Exemplo n.º 7
0
    def _ceiling(self, key, node):
        if node is None:
            return None

        if eq(key, node.key):
            return node

        if gt(key, node.key):
            return self._ceiling(key, node.right)

        left_subtree_ceiling = self._ceiling(key, node.left)
        return left_subtree_ceiling if left_subtree_ceiling is not None else node
Exemplo n.º 8
0
    def _floor(self, key, node):
        if node is None:
            return None

        if eq(key, node.key):
            return node

        if lt(key, node.key):
            return self._floor(key, node.left)

        right_subtree_floor = self._floor(key, node.right)
        return right_subtree_floor if right_subtree_floor is not None else node
Exemplo n.º 9
0
def binary_search(items, item):
    low = 0
    high = len(items) - 1

    while high >= low:
        mid = int(floor((high + low) / 2))
        if eq(items[mid], item):
            return mid

        if gt(item, items[mid]):
            low = mid + 1
        else:
            high = mid - 1
    return None
Exemplo n.º 10
0
    def range(self, low: Key = None, high: Key = None):
        rank_of_low = self.rank(low) if low is not None else 0
        rank_of_high = self.rank(high) if high is not None else len(
            self._items) - 1

        if rank_of_low > rank_of_high:
            return []

        result = []
        for i in range(rank_of_low, rank_of_high):
            result.append(self._items[i].key)

        if high is None or (0 <= rank_of_high < len(self._items)
                            and eq(self._items[rank_of_high].key, high)):
            result.append(self._items[rank_of_high].key)

        return result
Exemplo n.º 11
0
    def _put(self, new_node: Node, position: Node):
        if position is None:
            return new_node

        if eq(new_node.key, position.key):
            position.value = new_node.value
            return position

        if lt(new_node.key, position.key):
            position.left = self._put(new_node, position.left)
        else:
            position.right = self._put(new_node, position.right)

        position.node_count = (position.left.node_count if position.left is not None else 0) \
            + (position.right.node_count if position.right is not None else 0) \
            + 1

        return position
Exemplo n.º 12
0
def has_same_items(l1, l2):
    """
    This implementation takes O(n*log(n)) time mainly for sorting the two lists before comparing their items.

    Another implementation would be to loop over the first list, build a hash table from that list, and then
    loop over the second list to check if any item not in the hash table. Note that we also need to keep track of
    the item count to handle duplicated items. This implementation takes O(n) time.
    """

    if len(l1) != len(l2):
        return False

    sorted_l1 = quick_sort(l1)
    sorted_l2 = quick_sort(l2)

    for i in range(len(sorted_l1)):
        if not eq(sorted_l1[i], sorted_l2[i]):
            return False
    return True
Exemplo n.º 13
0
    def rank(self, key: Key):
        low = 0
        high = len(self._items) - 1
        while high >= low:
            mid = int(floor(high + low) / 2)
            if eq(key, self._items[mid].key):
                return mid
            if mid + 1 < len(self._items) and gt(
                    key, self._items[mid].key) and lt(
                        key, self._items[mid + 1].key):
                return mid + 1
            if gt(key, self._items[mid].key):
                low = mid + 1
            else:
                high = mid - 1

        if low >= len(self._items):
            return len(self._items)
        if high < 0:
            return 0
Exemplo n.º 14
0
 def _index_of_key(self, key):
     r = self.rank(key)
     return r if r < len(self._items) and eq(self._items[r].key,
                                             key) else None
Exemplo n.º 15
0
 def equals(self, other):
     return eq(self.value, other.value)
Exemplo n.º 16
0
 def equals(self, other):
     return eq(self.key, other.key)
Exemplo n.º 17
0
    def test_check_equals(self):
        assert eq(None, None)

        assert not eq(1, 2)
        assert eq(2, 2)
        assert not eq(2, 1)

        assert not eq(1.1, 1.2)
        assert not eq(2.1, 1.9)
        assert eq(2.1, 2.1)

        assert not eq(KeyValue(1), KeyValue(2))
        assert eq(KeyValue(2), KeyValue(2))
        assert not eq(KeyValue(2), KeyValue(1))

        assert not eq(KeyValue(Key(1)), KeyValue(Key(2)))
        assert eq(KeyValue(Key(2)), KeyValue(Key(2)))
        assert not eq(KeyValue(Key(2)), KeyValue(Key(1)))