コード例 #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
コード例 #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
コード例 #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
コード例 #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)
コード例 #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)
コード例 #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
コード例 #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
コード例 #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
コード例 #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
コード例 #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
コード例 #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
コード例 #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
コード例 #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
コード例 #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
コード例 #15
0
 def equals(self, other):
     return eq(self.value, other.value)
コード例 #16
0
 def equals(self, other):
     return eq(self.key, other.key)
コード例 #17
0
ファイル: utils_test.py プロジェクト: khanhpdt/dsalgs-python
    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)))