def partition(items, start, end): if start >= end: return None partitioning_item = items[start] left = start right = end + 1 while True: # scan from the left to find the item not in correct position, i.e., item > partitioning item left = left + 1 while left <= end and lt_or_eq(items[left], partitioning_item): left = left + 1 # scan from the right to find the item not in correct position, i.e., item < partitioning item right = right - 1 while right > start and gt_or_eq(items[right], partitioning_item): right = right - 1 # partitioning done. what's left is to move the partitioning item to the right position. if left >= right: break exchange(items, left, right) exchange(items, start, right) return right
def _satisfy_binary_search_tree_property(self, node: Node): if node is None: return True node_satisfy = (node.left is None or gt_or_eq(node, node.left)) \ and (node.right is None or lt_or_eq(node, node.right)) return node_satisfy \ and self._satisfy_binary_search_tree_property(node.left) \ and self._satisfy_binary_search_tree_property(node.right)
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)
def range(self, low: Key = None, high: Key = None): result = [] for item in self._items: key = item.key in_range = True if low is not None: in_range = gt_or_eq(key, low) if in_range and high is not None: in_range = lt_or_eq(key, high) if in_range: result.append(key) return result
def select_child(self, child1, child1_idx, child2, child2_idx): return child1_idx if lt_or_eq(child1, child2) else child2_idx
def hold_for_item(self, item, parent): return lt_or_eq(parent, item)