From 1d384dd85ec1c5645f358d070c5bafcef705d80c Mon Sep 17 00:00:00 2001 From: Joohwan Oh Date: Wed, 20 May 2020 16:13:20 -0400 Subject: [PATCH] Change Node.value to Node.val and minor refactors --- README.rst | 6 +- binarytree/__init__.py | 248 ++++++++++++++++++++--------------------- binarytree/version.py | 2 +- docs/index.rst | 2 +- docs/overview.rst | 2 +- tests/test_tree.py | 106 +++++++++--------- 6 files changed, 180 insertions(+), 186 deletions(-) diff --git a/README.rst b/README.rst index 8cf45fe..81e3c41 100644 --- a/README.rst +++ b/README.rst @@ -9,7 +9,7 @@ Binarytree: Python Library for Studying Binary Trees :target: https://badge.fury.io/py/binarytree :alt: Package Version -.. image:: https://img.shields.io/badge/python-2.7%2C%203.5%2C%203.6%2C%203.7-blue.svg +.. image:: https://img.shields.io/badge/python-2.7%2C%203.5%2C%203.6%2C%203.7%2C%203.8-blue.svg :target: https://github.com/joowani/binarytree :alt: Python Versions @@ -50,7 +50,7 @@ Announcements Requirements ============ -- Python 2.7, 3.4, 3.5, 3.6 or 3.7. +- Python 2.7, 3.4, 3.5, 3.6, 3.7, 3.8 Installation ============ @@ -82,7 +82,7 @@ By default, **binarytree** uses the following class to represent a node: class Node(object): def __init__(self, value, left=None, right=None): - self.value = value # The node value + self.val = value # The node value self.left = left # Left child self.right = right # Right child diff --git a/binarytree/__init__.py b/binarytree/__init__.py index cb489ab..7e20116 100644 --- a/binarytree/__init__.py +++ b/binarytree/__init__.py @@ -16,6 +16,11 @@ NodeReferenceError, ) +LEFT = 'left' +RIGHT = 'right' +VAL = 'val' +VALUE = 'value' + def _is_balanced(root): """Return the tree height + 1 if balanced, -1 otherwise. @@ -51,9 +56,9 @@ def _is_bst(root, min_value=float('-inf'), max_value=float('inf')): if root is None: return True return ( - min_value < root.value < max_value and - _is_bst(root.left, min_value, root.value) and - _is_bst(root.right, root.value, max_value) + min_value < root.val < max_value and + _is_bst(root.left, min_value, root.val) and + _is_bst(root.right, root.val, max_value) ) @@ -65,16 +70,18 @@ def _is_symmetric(root): :return: True if the binary tree is symmetric, False otherwise. :rtype: bool """ + def symmetric_helper(left_subtree, right_subtree): if left_subtree is None and right_subtree is None: return True if left_subtree is None or right_subtree is None: return False return ( - left_subtree.value == right_subtree.value and + left_subtree.val == right_subtree.val and symmetric_helper(left_subtree.left, right_subtree.right) and symmetric_helper(left_subtree.right, right_subtree.left) ) + return symmetric_helper(root, root) @@ -184,9 +191,9 @@ def _build_tree_string(root, curr_index, index=False, delimiter='-'): line1 = [] line2 = [] if index: - node_repr = '{}{}{}'.format(curr_index, delimiter, root.value) + node_repr = '{}{}{}'.format(curr_index, delimiter, root.val) else: - node_repr = str(root.value) + node_repr = str(root.val) new_root_width = gap_size = len(node_repr) @@ -246,26 +253,26 @@ def _get_tree_properties(root): """ is_descending = True is_ascending = True - min_node_value = root.value - max_node_value = root.value + min_node_value = root.val + max_node_value = root.val size = 0 leaf_count = 0 min_leaf_depth = 0 max_leaf_depth = -1 is_strict = True is_complete = True - current_nodes = [root] + current_level = [root] non_full_node_seen = False - while len(current_nodes) > 0: + while len(current_level) > 0: max_leaf_depth += 1 - next_nodes = [] + next_level = [] - for node in current_nodes: + for node in current_level: size += 1 - value = node.value - min_node_value = min(value, min_node_value) - max_node_value = max(value, max_node_value) + val = node.val + min_node_value = min(val, min_node_value) + max_node_value = max(val, max_node_value) # Node is a leaf. if node.left is None and node.right is None: @@ -274,21 +281,21 @@ def _get_tree_properties(root): leaf_count += 1 if node.left is not None: - if node.left.value > value: + if node.left.val > val: is_descending = False - elif node.left.value < value: + elif node.left.val < val: is_ascending = False - next_nodes.append(node.left) + next_level.append(node.left) is_complete = not non_full_node_seen else: non_full_node_seen = True if node.right is not None: - if node.right.value > value: + if node.right.val > val: is_descending = False - elif node.right.value < value: + elif node.right.val < val: is_ascending = False - next_nodes.append(node.right) + next_level.append(node.right) is_complete = not non_full_node_seen else: non_full_node_seen = True @@ -296,7 +303,7 @@ def _get_tree_properties(root): # If we see a node with only one child, it is not strict is_strict &= (node.left is None) == (node.right is None) - current_nodes = next_nodes + current_level = next_level return { 'height': max_leaf_depth, @@ -317,10 +324,10 @@ def _get_tree_properties(root): class Node(object): """Represents a binary tree node. - This class provides methods and properties for managing the current node - instance, and the binary tree in which the node is the root of. When a - docstring in this class mentions "binary tree", it is referring to the - current node and its descendants. + This class provides methods and properties for managing the current node, + and the binary tree in which the node is the root of. When a docstring in + this class mentions "binary tree", it is referring to the current node as + well as all its descendants. :param value: Node value (must be a number). :type value: int | float | numbers.Number @@ -342,7 +349,7 @@ def __init__(self, value, left=None, right=None): if right is not None and not isinstance(right, Node): raise NodeTypeError('right child must be a Node instance') - self.value = value + self.value = self.val = value self.left = left self.right = right @@ -361,7 +368,7 @@ def __repr__(self): >>> Node(1) Node(1) """ - return 'Node({})'.format(self.value) + return 'Node({})'.format(self.val) def __str__(self): """Return the pretty-print string for the binary tree. @@ -430,21 +437,25 @@ def __setattr__(self, attr, obj): >>> from binarytree import Node >>> >>> node = Node(1) - >>> node.value = 'invalid' # doctest: +IGNORE_EXCEPTION_DETAIL + >>> node.val = 'invalid' # doctest: +IGNORE_EXCEPTION_DETAIL Traceback (most recent call last): ... NodeValueError: node value must be a number """ - if attr == 'left': + if attr == LEFT: if obj is not None and not isinstance(obj, Node): - raise NodeTypeError( - 'left child must be a Node instance') - elif attr == 'right': + raise NodeTypeError('left child must be a Node instance') + elif attr == RIGHT: if obj is not None and not isinstance(obj, Node): - raise NodeTypeError( - 'right child must be a Node instance') - elif attr == 'value' and not isinstance(obj, numbers.Number): - raise NodeValueError('node value must be a number') + raise NodeTypeError('right child must be a Node instance') + elif attr == VALUE: + if not isinstance(obj, numbers.Number): + raise NodeValueError('node value must be a number') + object.__setattr__(self, VAL, obj) + elif attr == VAL: + if not isinstance(obj, numbers.Number): + raise NodeValueError('node value must be a number') + object.__setattr__(self, VALUE, obj) object.__setattr__(self, attr, obj) @@ -480,17 +491,17 @@ def __iter__(self): >>> [node for node in root] [Node(1), Node(2), Node(3), Node(4), Node(5)] """ - current_nodes = [self] + current_level = [self] - while len(current_nodes) > 0: - next_nodes = [] - for node in current_nodes: + while len(current_level) > 0: + next_level = [] + for node in current_level: yield node if node.left is not None: - next_nodes.append(node.left) + next_level.append(node.left) if node.right is not None: - next_nodes.append(node.right) - current_nodes = next_nodes + next_level.append(node.right) + current_level = next_level def __len__(self): """Return the total number of nodes in the binary tree. @@ -554,15 +565,15 @@ def __getitem__(self, index): raise NodeIndexError( 'node index must be a non-negative int') - current_nodes = [self] + current_level = [self] current_index = 0 has_more_nodes = True while has_more_nodes: has_more_nodes = False - next_nodes = [] + next_level = [] - for node in current_nodes: + for node in current_level: if current_index == index: if node is None: break @@ -571,13 +582,13 @@ def __getitem__(self, index): current_index += 1 if node is None: - next_nodes.extend((None, None)) + next_level.extend((None, None)) continue - next_nodes.extend((node.left, node.right)) + next_level.extend((node.left, node.right)) if node.left is not None or node.right is not None: has_more_nodes = True - current_nodes = next_nodes + current_level = next_level raise NodeNotFoundError('node missing at index {}'.format(index)) @@ -652,7 +663,7 @@ def __setitem__(self, index, node): raise NodeNotFoundError( 'parent node missing at index {}'.format(parent_index)) - setattr(parent, 'left' if index % 2 else 'right', node) + setattr(parent, LEFT if index % 2 else RIGHT, node) def __delitem__(self, index): """Remove the node (or subtree) at the given level-order_ index. @@ -711,7 +722,7 @@ def __delitem__(self, index): raise NodeNotFoundError( 'no node to delete at index {}'.format(index)) - child_attr = 'left' if index % 2 == 1 else 'right' + child_attr = LEFT if index % 2 == 1 else RIGHT if getattr(parent, child_attr) is None: raise NodeNotFoundError( 'no node to delete at index {}'.format(index)) @@ -798,11 +809,11 @@ def validate(self): while has_more_nodes: has_more_nodes = False - next_nodes = [] + next_level = [] for node in to_visit: if node is None: - next_nodes.extend((None, None)) + next_level.extend((None, None)) else: if node in visited: raise NodeReferenceError( @@ -810,16 +821,16 @@ def validate(self): if not isinstance(node, Node): raise NodeTypeError( 'invalid node instance at index {}'.format(index)) - if not isinstance(node.value, numbers.Number): + if not isinstance(node.val, numbers.Number): raise NodeValueError( 'invalid node value at index {}'.format(index)) if node.left is not None or node.right is not None: has_more_nodes = True visited.add(node) - next_nodes.extend((node.left, node.right)) + next_level.extend((node.left, node.right)) index += 1 - to_visit = next_nodes + to_visit = next_level @property def values(self): @@ -850,26 +861,26 @@ def values(self): >>> root.values [1, 2, 3, None, 4] """ - current_nodes = [self] + current_level = [self] has_more_nodes = True values = [] while has_more_nodes: has_more_nodes = False - next_nodes = [] - for node in current_nodes: + next_level = [] + for node in current_level: if node is None: values.append(None) - next_nodes.extend((None, None)) + next_level.extend((None, None)) continue if node.left is not None or node.right is not None: has_more_nodes = True - values.append(node.value) - next_nodes.extend((node.left, node.right)) + values.append(node.val) + next_level.extend((node.left, node.right)) - current_nodes = next_nodes + current_level = next_level # Get rid of trailing None's while values and values[-1] is None: @@ -908,20 +919,20 @@ def leaves(self): >>> root.leaves [Node(3), Node(4)] """ - current_nodes = [self] + current_level = [self] leaves = [] - while len(current_nodes) > 0: - next_nodes = [] - for node in current_nodes: + while len(current_level) > 0: + next_level = [] + for node in current_level: if node.left is None and node.right is None: leaves.append(node) continue if node.left is not None: - next_nodes.append(node.left) + next_level.append(node.left) if node.right is not None: - next_nodes.append(node.right) - current_nodes = next_nodes + next_level.append(node.right) + current_level = next_level return leaves @property @@ -954,18 +965,18 @@ def levels(self): >>> root.levels [[Node(1)], [Node(2), Node(3)], [Node(4)]] """ - current_nodes = [self] + current_level = [self] levels = [] - while len(current_nodes) > 0: - next_nodes = [] - for node in current_nodes: + while len(current_level) > 0: + next_level = [] + for node in current_level: if node.left is not None: - next_nodes.append(node.left) + next_level.append(node.left) if node.right is not None: - next_nodes.append(node.right) - levels.append(current_nodes) - current_nodes = next_nodes + next_level.append(node.right) + levels.append(current_level) + current_level = next_level return levels @property @@ -1536,20 +1547,18 @@ def inorder(self): >>> root.inorder [Node(4), Node(2), Node(5), Node(1), Node(3)] """ - node_stack = [] result = [] + stack = [] node = self - while True: - if node is not None: - node_stack.append(node) + while node or stack: + while node: + stack.append(node) node = node.left - elif len(node_stack) > 0: - node = node_stack.pop() + if stack: + node = stack.pop() result.append(node) node = node.right - else: - break return result @@ -1587,17 +1596,15 @@ def preorder(self): >>> root.preorder [Node(1), Node(2), Node(4), Node(5), Node(3)] """ - node_stack = [self] result = [] + stack = [self] - while len(node_stack) > 0: - node = node_stack.pop() - result.append(node) - - if node.right is not None: - node_stack.append(node.right) - if node.left is not None: - node_stack.append(node.left) + while stack: + node = stack.pop() + if node: + result.append(node) + stack.append(node.right) + stack.append(node.left) return result @@ -1635,32 +1642,17 @@ def postorder(self): >>> root.postorder [Node(4), Node(5), Node(2), Node(3), Node(1)] """ - node_stack = [] result = [] - node = self - - while True: - while node is not None: - if node.right is not None: - node_stack.append(node.right) - node_stack.append(node) - node = node.left + stack = [self] - node = node_stack.pop() - if (node.right is not None and - len(node_stack) > 0 and - node_stack[-1] is node.right): - node_stack.pop() - node_stack.append(node) - node = node.right - else: + while stack: + node = stack.pop() + if node: result.append(node) - node = None + stack.append(node.left) + stack.append(node.right) - if len(node_stack) == 0: - break - - return result + return result[::-1] @property def levelorder(self): @@ -1697,18 +1689,18 @@ def levelorder(self): >>> root.levelorder [Node(1), Node(2), Node(3), Node(4), Node(5)] """ - current_nodes = [self] + current_level = [self] result = [] - while len(current_nodes) > 0: - next_nodes = [] - for node in current_nodes: + while len(current_level) > 0: + next_level = [] + for node in current_level: result.append(node) if node.left is not None: - next_nodes.append(node.left) + next_level.append(node.left) if node.right is not None: - next_nodes.append(node.right) - current_nodes = next_nodes + next_level.append(node.right) + current_level = next_level return result @@ -1766,7 +1758,7 @@ def build(values): if parent is None: raise NodeNotFoundError( 'parent node missing at index {}'.format(parent_index)) - setattr(parent, 'left' if index % 2 else 'right', node) + setattr(parent, LEFT if index % 2 else RIGHT, node) return nodes[0] if nodes else None @@ -1830,7 +1822,7 @@ def tree(height=3, is_perfect=False): inserted = False while depth < height and not inserted: - attr = random.choice(('left', 'right')) + attr = random.choice((LEFT, RIGHT)) if getattr(node, attr) is None: setattr(node, attr, Node(value)) inserted = True @@ -1896,7 +1888,7 @@ def bst(height=3, is_perfect=False): inserted = False while depth < height and not inserted: - attr = 'left' if node.value > value else 'right' + attr = LEFT if node.val > value else RIGHT if getattr(node, attr) is None: setattr(node, attr, Node(value)) inserted = True diff --git a/binarytree/version.py b/binarytree/version.py index 69acc14..af142cb 100644 --- a/binarytree/version.py +++ b/binarytree/version.py @@ -1 +1 @@ -__version__ = '4.1.0' # pragma: no cover +__version__ = '5.0.0' # pragma: no cover diff --git a/docs/index.rst b/docs/index.rst index ab4382b..ae518ec 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -11,7 +11,7 @@ algorithms. Heaps and BSTs (binary search trees) are also supported. Requirements ============ -- Python 2.7, 3.5, 3.6 or 3.7 +- Python 2.7, 3.5, 3.6, 3.7, 3.8 Installation ============ diff --git a/docs/overview.rst b/docs/overview.rst index 8184920..8de6bf8 100644 --- a/docs/overview.rst +++ b/docs/overview.rst @@ -8,7 +8,7 @@ By default, **binarytree** uses the following class to represent a node: class Node(object): def __init__(self, value, left=None, right=None): - self.value = value # The node value + self.val = value # The node value self.left = left # Left child self.right = right # Right child diff --git a/tests/test_tree.py b/tests/test_tree.py index 06a4184..d3e681f 100644 --- a/tests/test_tree.py +++ b/tests/test_tree.py @@ -24,39 +24,48 @@ REPETITIONS = 20 -@pytest.mark.order1 def test_node_set_attributes(): root = Node(1) assert root.left is None assert root.right is None + assert root.val == 1 assert root.value == 1 assert repr(root) == 'Node(1)' + root.value = 2 + assert root.value == 2 + assert root.val == 2 + assert repr(root) == 'Node(2)' + + root.val = 1 + assert root.value == 1 + assert root.val == 1 + assert repr(root) == 'Node(1)' + left_child = Node(2) root.left = left_child assert root.left is left_child assert root.right is None - assert root.value == 1 + assert root.val == 1 assert root.left.left is None assert root.left.right is None - assert root.left.value == 2 + assert root.left.val == 2 assert repr(left_child) == 'Node(2)' right_child = Node(3) root.right = right_child assert root.left is left_child assert root.right is right_child - assert root.value == 1 + assert root.val == 1 assert root.right.left is None assert root.right.right is None - assert root.right.value == 3 + assert root.right.val == 3 assert repr(right_child) == 'Node(3)' last_node = Node(4) left_child.right = last_node assert root.left.right is last_node - assert root.left.right.value == 4 - assert repr(last_node) == 'Node(4)' + assert repr(root.left.right) == 'Node(4)' with pytest.raises(NodeValueError) as err: # noinspection PyTypeChecker @@ -73,6 +82,11 @@ def test_node_set_attributes(): Node(1, Node(1), 'this_is_not_a_node') assert str(err.value) == 'right child must be a Node instance' + with pytest.raises(NodeValueError) as err: + root.val = 'this_is_not_an_integer' + assert root.val == 1 + assert str(err.value) == 'node value must be a number' + with pytest.raises(NodeValueError) as err: root.value = 'this_is_not_an_integer' assert root.value == 1 @@ -89,36 +103,36 @@ def test_node_set_attributes(): assert str(err.value) == 'right child must be a Node instance' -@pytest.mark.order2 +# noinspection PyUnresolvedReferences def test_tree_build(): root = build([]) assert root is None root = build([1]) - assert root.value == 1 + assert root.val == 1 assert root.left is None assert root.right is None root = build([1, 2]) - assert root.value == 1 - assert root.left.value == 2 + assert root.val == 1 + assert root.left.val == 2 assert root.right is None root = build([1, 2, 3]) - assert root.value == 1 - assert root.left.value == 2 - assert root.right.value == 3 + assert root.val == 1 + assert root.left.val == 2 + assert root.right.val == 3 assert root.left.left is None assert root.left.right is None assert root.right.left is None assert root.right.right is None root = build([1, 2, 3, None, 4]) - assert root.value == 1 - assert root.left.value == 2 - assert root.right.value == 3 + assert root.val == 1 + assert root.left.val == 2 + assert root.right.val == 3 assert root.left.left is None - assert root.left.right.value == 4 + assert root.left.right.val == 4 assert root.right.left is None assert root.right.right is None assert root.left.right.left is None @@ -133,7 +147,6 @@ def test_tree_build(): assert str(err.value) == 'parent node missing at index 1' -@pytest.mark.order3 def test_tree_get_node(): root = Node(1) root.left = Node(2) @@ -159,7 +172,6 @@ def test_tree_get_node(): assert str(err.value) == 'node index must be a non-negative int' -@pytest.mark.order4 def test_tree_set_node(): root = Node(1) root.left = Node(2) @@ -185,20 +197,20 @@ def test_tree_set_node(): assert str(err.value) == 'parent node missing at index 49' root[10] = new_node_1 - assert root.value == 1 - assert root.left.value == 2 - assert root.right.value == 3 - assert root.left.left.value == 4 - assert root.left.right.value == 5 - assert root.left.right.left.value == 6 + assert root.val == 1 + assert root.left.val == 2 + assert root.right.val == 3 + assert root.left.left.val == 4 + assert root.left.right.val == 5 + assert root.left.right.left.val == 6 assert root.left.right.right is new_node_1 root[4] = new_node_2 - assert root.value == 1 - assert root.left.value == 2 - assert root.right.value == 3 - assert root.left.left.value == 4 - assert root.left.right.value == 8 + assert root.val == 1 + assert root.left.val == 2 + assert root.right.val == 3 + assert root.left.left.val == 4 + assert root.left.right.val == 8 assert root.left.right.left is None assert root.left.right.right is None @@ -208,7 +220,6 @@ def test_tree_set_node(): assert root.right is new_node_2 -@pytest.mark.order5 def test_tree_del_node(): root = Node(1) root.left = Node(2) @@ -235,23 +246,23 @@ def test_tree_del_node(): del root[3] assert root.left.left is None - assert root.left.value == 2 - assert root.left.right.value == 5 + assert root.left.val == 2 + assert root.left.right.val == 5 assert root.left.right.right is None - assert root.left.right.left.value == 6 + assert root.left.right.left.val == 6 assert root.left.right.left.left is None assert root.left.right.left.right is None - assert root.right.value == 3 + assert root.right.val == 3 assert root.right.left is None assert root.right.right is None assert root.size == 5 del root[2] assert root.left.left is None - assert root.left.value == 2 - assert root.left.right.value == 5 + assert root.left.val == 2 + assert root.left.right.val == 5 assert root.left.right.right is None - assert root.left.right.left.value == 6 + assert root.left.right.left.val == 6 assert root.left.right.left.left is None assert root.left.right.left.right is None assert root.right is None @@ -269,7 +280,6 @@ def test_tree_del_node(): assert root.size == 1 -@pytest.mark.order6 def test_tree_print_no_index(): for printer in [builtin_print, pprint_default]: lines = printer([1]) @@ -312,7 +322,6 @@ def test_tree_print_no_index(): '8 5 6 7'] -@pytest.mark.order7 def test_tree_print_with_index(): lines = pprint_with_index([1]) assert lines == ['0:1'] @@ -354,7 +363,6 @@ def test_tree_print_with_index(): '3:8 4:5 5:6 6:7'] -@pytest.mark.order8 def test_tree_validate(): class TestNode(Node): @@ -389,7 +397,7 @@ def __setattr__(self, attr, value): root = TestNode(1) root.right = TestNode(2) - root.right.value = 'not_an_integer' + root.right.val = 'not_an_integer' with pytest.raises(NodeValueError) as err: root.validate() assert str(err.value) == 'invalid node value at index 2' @@ -402,7 +410,6 @@ def __setattr__(self, attr, value): assert str(err.value) == 'cyclic node reference at index 4' -@pytest.mark.order9 def test_tree_properties(): root = Node(1) assert root.properties == { @@ -643,7 +650,6 @@ def test_tree_properties(): assert root.size == len(root) == 7 -@pytest.mark.order10 def test_tree_traversal(): n1 = Node(1) assert n1.levels == [[n1]] @@ -707,7 +713,6 @@ def test_tree_list_representation(): assert root.values == [1, 2, 3, 6, 7, 4, 5] -@pytest.mark.order11 def test_tree_generation(): for invalid_height in ['foo', -1, None]: with pytest.raises(TreeHeightError) as err: @@ -719,7 +724,7 @@ def test_tree_generation(): assert root.height == 0 assert root.left is None assert root.right is None - assert isinstance(root.value, int) + assert isinstance(root.val, int) for _ in range(REPETITIONS): random_height = random.randint(1, 9) @@ -737,7 +742,6 @@ def test_tree_generation(): assert root.is_strict is True -@pytest.mark.order12 def test_bst_generation(): for invalid_height in ['foo', -1, None]: with pytest.raises(TreeHeightError) as err: @@ -749,7 +753,7 @@ def test_bst_generation(): assert root.height == 0 assert root.left is None assert root.right is None - assert isinstance(root.value, int) + assert isinstance(root.val, int) for _ in range(REPETITIONS): random_height = random.randint(1, 9) @@ -774,7 +778,6 @@ def test_bst_generation(): assert root.is_strict is True -@pytest.mark.order13 def test_heap_generation(): for invalid_height in ['foo', -1, None]: with pytest.raises(TreeHeightError) as err: @@ -786,7 +789,7 @@ def test_heap_generation(): assert root.height == 0 assert root.left is None assert root.right is None - assert isinstance(root.value, int) + assert isinstance(root.val, int) for _ in range(REPETITIONS): random_height = random.randint(1, 9) @@ -816,7 +819,6 @@ def test_heap_generation(): assert root.height == random_height -@pytest.mark.order13 def test_heap_float_values(): root = Node(1.0) root.left = Node(0.5)