mirror of
https://github.com/autistic-symposium/master-algorithms-py.git
synced 2025-05-06 08:45:11 -04:00
Rename SimpleTree.py to simple_tree.py
This commit is contained in:
parent
ff1a7e5d51
commit
4475910493
1 changed files with 0 additions and 0 deletions
296
trees/simple_tree.py
Normal file
296
trees/simple_tree.py
Normal file
|
@ -0,0 +1,296 @@
|
|||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
# author: bt3gl
|
||||
|
||||
|
||||
class SimpleTree:
|
||||
"""Implementation of a simple tree"""
|
||||
|
||||
def __init__(self, value=None, node=None):
|
||||
self.value = value
|
||||
self.node = node or []
|
||||
|
||||
def __repr__(self, level=0):
|
||||
repr = '\t' * level + self.value + '\n'
|
||||
for n in self.node:
|
||||
repr += n.__repr__(level + 1)
|
||||
return repr
|
||||
|
||||
|
||||
class Node():
|
||||
"""Implementation of a Node for a binary tree"""
|
||||
|
||||
def __init__(self, value=None):
|
||||
self.value = value
|
||||
self.left = None
|
||||
self.right = None
|
||||
|
||||
############################
|
||||
# Private Methods
|
||||
############################
|
||||
def __repr__(self):
|
||||
"""Prints the node"""
|
||||
return f'{self.value}'
|
||||
|
||||
def _repr_preorder(self):
|
||||
"""Prints the tree in preorder traversal (root, left, right)"""
|
||||
|
||||
print(self.value)
|
||||
if self.left:
|
||||
self.left._repr_preorder()
|
||||
if self.right:
|
||||
self.right._repr_preorder()
|
||||
|
||||
def _add_node_binary_tree(self, value):
|
||||
"""Adds a node to a simple binary tree"""
|
||||
|
||||
if self.value is None:
|
||||
self.value = value
|
||||
|
||||
else:
|
||||
if not self.left:
|
||||
self.left = Node(value)
|
||||
elif not self.right:
|
||||
self.right = Node(value)
|
||||
else:
|
||||
self.left = self.left._add_node_binary_tree(value)
|
||||
|
||||
return self
|
||||
|
||||
def _add_node_binary_search_tree(self, value) -> bool:
|
||||
"""Adds a node to a binary search tree"""
|
||||
|
||||
if not self.value:
|
||||
self.value = value
|
||||
|
||||
else:
|
||||
new_node = Node(value)
|
||||
if value < self.value:
|
||||
self.left = self.left and self.left._add_node_binary_search_tree(value) or new_node
|
||||
elif value > self.value:
|
||||
self.right = self.right and self.right._add_node_binary_search_tree(value) or new_node
|
||||
else:
|
||||
print(f'❌ Item {value} not added as BSTs do not support repetition.')
|
||||
|
||||
return self
|
||||
|
||||
def _search_node_preorder(self, query) -> bool:
|
||||
"""Searches through preorder traversal (node, left, right)"""
|
||||
|
||||
if self.value == query:
|
||||
return True
|
||||
|
||||
found = False
|
||||
if self.left:
|
||||
# recursively search left
|
||||
found = self.left._search_node_preorder(query)
|
||||
|
||||
if self.right:
|
||||
# recursively search right
|
||||
found = found or self.right._search_node_preorder(query)
|
||||
|
||||
return found
|
||||
|
||||
def _search_node_binary_search_tree(self, query) -> bool:
|
||||
"""Searches the tree for a value, considering the BST property"""
|
||||
|
||||
this_node_value = self.value
|
||||
|
||||
if this_node_value is not None:
|
||||
if this_node_value == query:
|
||||
return True
|
||||
|
||||
elif this_node_value > query:
|
||||
if self.left is not None:
|
||||
return self.left._search_node_binary_search_tree(query)
|
||||
|
||||
elif this_node_value < query:
|
||||
if self.right is not None:
|
||||
return self.right._search_node_binary_search_tree(query)
|
||||
|
||||
return False
|
||||
|
||||
def _is_leaf(self) -> bool:
|
||||
"""If node has no children, it is a leaf"""
|
||||
|
||||
return bool(not self.right and not self.left)
|
||||
|
||||
def _is_full(self) -> bool:
|
||||
"""If node has two children, it is full"""
|
||||
return bool(self.right and self.left)
|
||||
|
||||
|
||||
class BinaryTreeInterface():
|
||||
|
||||
def __init__(self):
|
||||
self.root = Node()
|
||||
|
||||
############################
|
||||
# Interface Methods
|
||||
############################
|
||||
def add_node(self, value):
|
||||
"""Adds a new node to the tree"""
|
||||
pass
|
||||
|
||||
def search_node(self, value):
|
||||
"""Searches the tree for a value"""
|
||||
pass
|
||||
|
||||
############################
|
||||
# Public Methods
|
||||
############################
|
||||
def is_leaf(self) -> bool:
|
||||
"""Returns True if the node is a leaf"""
|
||||
|
||||
if self.root is not None:
|
||||
return self.root._is_leaf()
|
||||
|
||||
def is_full(self) -> bool:
|
||||
"""Returns True if the node is full"""
|
||||
|
||||
if self.root is not None:
|
||||
return self.root._is_full()
|
||||
|
||||
def print_preorder(self):
|
||||
"""Prints the BST in preorder"""
|
||||
|
||||
if self.root is not None:
|
||||
self.root._repr_preorder()
|
||||
|
||||
############################
|
||||
# Class Methods
|
||||
############################
|
||||
@classmethod
|
||||
def is_balanced(cls, node, left=0, right=0) -> bool:
|
||||
"""Returns True if the tree is balanced"""
|
||||
|
||||
if node is None:
|
||||
return (left - right) < 2
|
||||
|
||||
else:
|
||||
return cls.is_balanced(node.left, left + 1, right) and \
|
||||
cls.is_balanced(node.right, left, right + 1)
|
||||
|
||||
@classmethod
|
||||
def is_binary_search_tree(cls, node, min_node=None, max_node=None) -> bool:
|
||||
"""Returns True if the tree is a BST"""
|
||||
|
||||
min_node = min_node or float('-inf')
|
||||
max_node = max_node or float('inf')
|
||||
|
||||
if not node:
|
||||
return True
|
||||
|
||||
if node.value < min_node or node.value > max_node:
|
||||
return False
|
||||
|
||||
return cls.is_binary_search_tree(node.left, min_node, node.value) and \
|
||||
cls.is_binary_search_tree(node.right, node.value, max_node)
|
||||
|
||||
|
||||
|
||||
class BinaryTree(BinaryTreeInterface):
|
||||
"""Implementation of a binary tree"""
|
||||
|
||||
def add_node(self, value):
|
||||
"""Adds a new node to the tree"""
|
||||
|
||||
if self.root is None:
|
||||
self.root = Node(value)
|
||||
else:
|
||||
self.root._add_node_binary_tree(value)
|
||||
|
||||
def search_node(self, value):
|
||||
"""Searches the tree for a value"""
|
||||
|
||||
if self.root:
|
||||
return self.root._search_node_preorder(value)
|
||||
|
||||
|
||||
class BinarySearchTree(BinaryTreeInterface):
|
||||
|
||||
def add_node(self, value):
|
||||
"""Adds a new node to the tree"""
|
||||
|
||||
if self.root is None:
|
||||
self.root = Node(value)
|
||||
else:
|
||||
self.root._add_node_binary_search_tree(value)
|
||||
|
||||
def search_node(self, value):
|
||||
"""Searches the tree for a value"""
|
||||
|
||||
if self.root.value is not None:
|
||||
return self.root._search_node_binary_search_tree(value)
|
||||
|
||||
@classmethod
|
||||
def largest_node(cls, node):
|
||||
"""Returns the largest node in the tree"""
|
||||
|
||||
if node.right:
|
||||
return cls.largest_node(node.right)
|
||||
else:
|
||||
return node
|
||||
|
||||
@classmethod
|
||||
def smallest_node(cls, node):
|
||||
"""Returns the smallest node in the tree"""
|
||||
|
||||
if node.left:
|
||||
return cls.smallest_node(node.left)
|
||||
else:
|
||||
return node
|
||||
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
############################
|
||||
# Test SimpleTree
|
||||
############################
|
||||
print("\n\n🌴🌴🌴 Testing SimpleTree 🌴🌴🌴")
|
||||
t = SimpleTree('a', [SimpleTree('b', [SimpleTree('d'), SimpleTree('e')]), \
|
||||
SimpleTree('c', [SimpleTree('h'), SimpleTree('g')])])
|
||||
print(t)
|
||||
|
||||
|
||||
############################
|
||||
# Test binary tree
|
||||
############################
|
||||
print("\n\n🌳🌳🌳 Testing BinaryTree 🌳🌳🌳")
|
||||
bt = BinaryTree()
|
||||
array1 = [4, 1, 4, 6, 7, 9, 10, 5, 11, 5]
|
||||
print(f'\n🟡 Adding {array1} to the tree...')
|
||||
for i in array1:
|
||||
bt.add_node(i)
|
||||
print("🟢 Printing the tree in preorder...")
|
||||
bt.print_preorder()
|
||||
print(f'\n🟢 Searching for node 5: {bt.search_node(5)}')
|
||||
print(f'❌ Searching for node 15: {bt.search_node(15)}')
|
||||
print(f'❌ Is root a leaf? {bt.is_leaf()}')
|
||||
print(f'🟢 Is root full? {bt.is_full()}')
|
||||
print(f'❌ Is the tree balanced? {BinaryTree.is_balanced(bt.root)}')
|
||||
print(f'❌ Is the tree a binary search tree? {BinaryTree.is_binary_search_tree(bt.root)}')
|
||||
|
||||
|
||||
|
||||
##############################
|
||||
# Test binary search tree
|
||||
##############################
|
||||
print("\n\n🎄🎄🎄 Testing BinarySearchTree 🎄🎄🎄")
|
||||
bst = BinarySearchTree()
|
||||
array1 = [4, 1, 4, 6, 7, 9, 10, 5, 11, 5]
|
||||
print(f'\n🟡 Adding {array1} to the tree...')
|
||||
for i in array1:
|
||||
bst.add_node(i)
|
||||
print("🟢 Printing the tree in preorder:")
|
||||
bst.print_preorder()
|
||||
print(f'\n🟢 Searching for node 5: {bst.search_node(5)}')
|
||||
print(f'❌ Searching for node 15: {bst.search_node(15)}')
|
||||
print(f'❌ Is root a leaf? {bst.is_leaf()}')
|
||||
print(f'🟢 Is root full? {bst.is_full()}')
|
||||
print(f'🟢 Largest node? {bst.largest_node(bst.root)}')
|
||||
print(f'🟢 Smallest node? {bst.smallest_node(bst.root)}')
|
||||
print(f'❌ Is the tree balanced? {bst.is_balanced(bst.root)}')
|
||||
print(f'🟢 Is the tree a binary search tree? {bst.is_binary_search_tree(bst.root)}')
|
Loading…
Add table
Add a link
Reference in a new issue