About

binary_tree provides a Node object, node functions, and tree functions for a binary tree data structure.

Installation

To install binary_tree, run this in your terminal:

$ pip install git+git://github.com/han-keong/binary_tree

The conventional way of importing from binary_tree is to do:

from binary_tree import Node, node, tree

You may also import everything by doing:

from binary_tree import *

Features

Construct a node

Node attributes

Every Node has the following attributes:

Note

All the attributes above besides value should be instances of Node if they are present.

Node initialization

When initializing a Node, a value must be provided.

>>> left_node = Node(2)

Meanwhile, the other attributes can be set using keyword arguments.

>>> parent_node = Node(1, left=left_node)

Setting Node attributes

Attributes that are reciprocative are set automatically.

For example, when you set the left or right attribute of a Node instance, the child’s parent attribute is also set behind the scenes.

>>> left_node.parent is parent_node
True
>>> right_node = Node(3)
>>> parent_node.right = right_node
>>>
>>> right_node.parent is parent_node
True

Likewise, setting the prev or next attribute of a Node instance will affect the other corresponding neighbour attribute.

>>> right_node.prev = left_node
>>>
>>> left_node.next is right_node
True

Check a node

The following node functions can be used to check if a Node has certain properties.

is_node()

is_node() checks if an object is an instance of Node.

>>> node.is_node(parent_node)
True

is_left()

is_left() checks if an instance of Node is a left child.

>>> node.is_left(parent_node.left)
True

is_right()

is_right() checks if an instance of Node is a right child.

>>> node.is_right(parent_node.right)
True

is_leaf()

is_leaf() checks if an instance of Node is a leaf node.

>>> node.is_leaf(parent_node.right)
True

is_root()

is_root() checks if an instance of Node is a root node.

>>> node.is_root(parent_node):
True

is_orphan()

is_orphan() checks if an instance of Node is an orphan node.

>>> lonely_node = Node(1)
>>> node.is_orphan(lonely_node)
True

Equality tests

Node instances have a special way of testing equality, which is to tentatively compare the value of self and the other object.

If the other object does not have a value attribute, the object itself is taken as the basis of comparison.

This allows the following comparisons to work:

>>> parent_node == Node(1)
True
>>> parent_node == 1
True

If you would like to test if two instances of Node have the same binary tree structure, you may compare their repr() strings.

>>> parent_node2 = Node(1, left=Node(2), right=Node(3))
>>>
>>> repr(parent_node) == repr(parent_node2)
True

Set up a binary tree

The tree module contains all the relevant functions for binary tree structures.

from_string()

A tree string should be in level-order and separated by commas.

>>> tree_string = "1,2,3,4,5,6"

Empty spaces can be represented by an immediate comma or "null" to be explicit.

>>> tree_string = "1,2,3,4,,5,6"
>>> tree_string = "1,2,3,4,null,5,6"

Pass the string into from_string() to generate a Node instance with the desired binary tree structure.

>>> root = tree.from_string(tree_string)

You can use repr() to see the binary tree structure of the Node instance.

>>> repr(root)
"Node(1, left=Node(2, left=Node(4)), right=Node(3, left=Node(5), right=Node(6)))"

from_orders()

Another way to set up a binary tree structure is with its in-order and pre-order traversals.

>>> in_order = [4,2,1,5,3,6]
>>> pre_order = [1,2,4,3,5,6]

Pass the appropriate key and the traversals into from_orders() to generate a Node instance with the original tree structure.

>>> root = tree.from_orders("in-pre", in_order, pre_order)
>>> repr(root)
"Node(1, left=Node(2, left=Node(4)), right=Node(3, left=Node(5), right=Node(6)))"

Alternatively, you can use the in-order and post-order traversal.

>>> post_order = [4,2,5,6,3,1]
>>> root = tree.from_orders("in-post", in_order, post_order)
>>>
>>> repr(root)
"Node(1, left=Node(2, left=Node(4)), right=Node(3, left=Node(5), right=Node(6)))"

Note

There should not be duplicates present in in_order and pre_order or post_order.

connect_nodes()

When using the above methods to construct a Node instance, the neighbour nodes in each level of its binary tree structure are already connected using connect_nodes().

You may use this function again to reconfigure the tree structure of a root Node instance after modifying it, or to connect one that was manually set up.

>>> root.right.right = None  # Prune the right branch of the right child
>>> tree.connect_nodes(root)

to_string()

Just as a binary tree structure can be constructed from string, it can be deconstructed back into one too, using to_string().

>>> tree.to_string(root)
"1,2,3,4,,5"

Traverse a binary tree

With a binary tree structure set up, there are several tree functions you can use to traverse it.

traverse_pre_order()

traverse_pre_order() traverses the binary tree structure of a root Node instance in pre-order.

>>> list(tree.traverse_pre_order(root))
[Node(1), Node(2), Node(4), Node(3), Node(5)]

traverse_in_order()

traverse_in_order() traverses the binary tree structure of a root Node instance in in-order.

>>> list(tree.traverse_in_order(root))
[Node(4), Node(2), Node(1), Node(5), Node(3)]

traverse_post_order()

traverse_post_order() traverses the binary tree structure of a root Node instance in post-order.

>>> list(tree.traverse_post_order(root))
[Node(4), Node(2), Node(5), Node(3), Node(1)]

traverse_level_order()

traverse_level_order() traverses the binary tree structure of a root Node instance in level-order.

>>> list(tree.traverse_level_order(root))
[[Node(1)], [Node(2), Node(3)], [Node(4), Node(5)]]

Note

traverse_level_order() will yield lists containing instances of Node. Each list represents a level in the binary tree structure.

traverse()

A single dispatch function, traverse(), is available for convenience.

>>> list(tree.traverse(root, "pre"))
[Node(1), Node(2), Node(4), Node(3), Node(5)]
>>> list(tree.traverse(root, "in"))
[Node(4), Node(2), Node(1), Node(5), Node(3)]
>>> list(tree.traverse(root, "post"))
[Node(4), Node(2), Node(5), Node(3), Node(1)]
>>> list(tree.traverse(root, "level"))
[[Node(1)], [Node(2), Node(3)], [Node(4), Node(5)]]

Iterating over a Node

You can also iterate over an instance of Node to traverse its binary tree structure.

>>> for node in root:
...     print(node)
Node(1)
Node(2)
Node(3)
Node(4)
Node(5)

Note

Iteration over a Node instance goes by level-order traversal.

Analyze a binary tree

The following tree functions are available to find certain properties of a binary tree structure.

is_symmetrical()

is_symmetrical() checks for symmetry in the binary tree structure of a root Node instance.

>>> tree.is_symmetrical(root)
False

max_depth()

max_depth() calculates the maximum depth of the binary tree structure of a root Node instance.

>>> tree.max_depth(root)
3

get_path()

get_path() traces the ancestry of a Node instance.

>>> tree.get_path(root.right.left)
[Node(1), Node(3), Node(5)]

all_paths()

all_paths() finds every leaf path in the binary tree structure of a root Node instance.

>>> for path in tree.all_paths(root):
...     print(path)
[Node(1), Node(2), Node(4)]
[Node(1), Node(3), Node(5)]

Note

all_paths() searches for paths using post-order traversal.

has_sum()

has_sum() determines if there is a path in the binary tree structure of a root Node instance that adds up to a certain value.

>>> tree.has_sum(root, 7)
True

find_path()

find_path() finds the path of some Node instance or value in the binary tree structure of a root Node instance.

>>> tree.find_path(5)
[Node(1), Node(3), Node(5)]
>>> tree.find_path(2)
[Node(1), Node(2)]

get_lca()

get_lca() gets the lowest common ancestor of two or more Node instances or values in the binary tree structure of a root Node instance.

>>> tree.get_lca(root, 2, 4)
Node(2)
>>> tree.get_lca(root, 1, 3, 5)
Node(1)

Note

It is possible to pass the value of the Node instance you wish to refer to because of the way equality is tested for. However, the value must be unique within the binary tree structure.

Credits

binary_tree was written by Han Keong <hk997@live.com>.

This package was created with Cookiecutter and the audreyr/cookiecutter-pypackage project template.