コード例 #1
0
ファイル: quick_sort.py プロジェクト: khanhpdt/dsalgs-python
def partition_3way(items, start, end):
    if start >= end:
        return None, None

    partitioning_item = items[start]
    less_than_idx = start
    greater_than_idx = end

    # Invariant:
    #   - a[start..less_than_idx - 1] < partitioning_item
    #   - a[greater_than_idx + 1..end] > partitioning_item
    #   - a[less_than_idx..i-1] = partitioning_item
    #   - a[i..greater_than_idx] are not yet examined

    i = start + 1
    while i <= greater_than_idx:
        if lt(items[i], partitioning_item):
            # move items < partitioning_item to the left
            exchange(items, i, less_than_idx)
            less_than_idx = less_than_idx + 1
            # move the pointer because we know that the new item at the position i is
            # either equal or less than the partitioning item
            i = i + 1
        elif gt(items[i], partitioning_item):
            # move items > partitioning_item to the right
            exchange(items, i, greater_than_idx)
            greater_than_idx = greater_than_idx - 1
            # here, we don't move the pointer because we don't know how the new item
            # at the position i compares to the partitioning item
        else:
            # leave the items = partitioning_item where they are
            i = i + 1

    return less_than_idx, greater_than_idx
コード例 #2
0
    def min(self):
        if self.is_empty():
            return None

        current_min = self._items[0].key
        for i in range(1, self.size_of_range()):
            if lt(self._items[i].key, current_min):
                current_min = self._items[i].key
        return current_min
コード例 #3
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
コード例 #4
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
コード例 #5
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
コード例 #6
0
    def _range(self, node, low, high):
        if node is None:
            return []

        node_satisfy = (low is None or gt_or_eq(node.key, low)) \
            and (high is None or lt_or_eq(node.key, high))
        result = [node] if node_satisfy else []

        if low is not None and lt(node.key, low):
            return result + self._range(node.right, low, high)
        if high is not None and gt(node.key, high):
            return result + self._range(node.left, low, high)
        return result + self._range(node.left, low, high) + self._range(
            node.right, low, high)
コード例 #7
0
    def ceiling(self, key: Key):
        if self.is_empty():
            return None

        candidate = None
        for i in range(self.size_of_range()):
            current_item_key = self._items[i].key
            if current_item_key.equals(key):
                return current_item_key

            candidate = current_item_key \
                if gt(current_item_key, key) and (candidate is None or lt(current_item_key, candidate)) \
                else candidate

        return candidate
コード例 #8
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
コード例 #9
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
コード例 #10
0
 def rank(self, key: Key):
     result = 0
     for item in self._items:
         if lt(item.key, key):
             result = result + 1
     return result