mirror of
https://github.com/autistic-symposium/master-algorithms-py.git
synced 2025-06-06 06:08:49 -04:00
trees organized
This commit is contained in:
parent
28b84cef65
commit
52752fb931
16 changed files with 262 additions and 689 deletions
src/trees
215
src/trees/binary_tree.py
Normal file → Executable file
215
src/trees/binary_tree.py
Normal file → Executable file
|
@ -1,43 +1,23 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
__author__ = "Mari Wahl"
|
||||
__email__ = "marina.w4hl@gmail.com"
|
||||
__author__ = "bt3"
|
||||
|
||||
|
||||
class Node(object):
|
||||
|
||||
''' Implementation of a binary tree and its properties. For example, the following bt:
|
||||
def __init__(self, item=None,):
|
||||
|
||||
1 ---> level 0
|
||||
2 3 ---> level 1
|
||||
4 5 ---> level 2
|
||||
6 7 ---> level 3
|
||||
8 9 ---> level 4
|
||||
|
||||
has the following properties:
|
||||
|
||||
- SIZE OR NUMBER OF NODES: n = 9
|
||||
- NUMBER OF BRANCHES OR INTERNAL NODES: b = n-1 = 8
|
||||
- VALUE OF ROOT = 1
|
||||
- MAX_DEPTH OR HEIGHT: h = 4
|
||||
- IS BALANCED? NO
|
||||
- IS BST? NO
|
||||
'''
|
||||
|
||||
|
||||
class NodeBT(object):
|
||||
def __init__(self, item=None, level=0):
|
||||
self.item = item
|
||||
self.level = level
|
||||
self.left = None
|
||||
self.right = None
|
||||
|
||||
|
||||
def __repr__(self):
|
||||
return '{}'.format(self.item)
|
||||
|
||||
|
||||
def _addNextNode(self, value, level_here=1):
|
||||
new_node = NodeBT(value, level_here)
|
||||
def _add(self, value):
|
||||
new_node = Node(value)
|
||||
|
||||
if not self.item:
|
||||
self.item = new_node
|
||||
elif not self.left:
|
||||
|
@ -45,162 +25,93 @@ class NodeBT(object):
|
|||
elif not self.right:
|
||||
self.right = new_node
|
||||
else:
|
||||
self.left = self.left._addNextNode(value, level_here+1)
|
||||
return self ## this is important, because the node return to the main
|
||||
self.left = self.left._add(value)
|
||||
return self
|
||||
|
||||
|
||||
def _searchForNode(self, value):
|
||||
def _search(self, value):
|
||||
if self.item == value:
|
||||
return self
|
||||
else:
|
||||
found = None
|
||||
if self.left:
|
||||
found = self.left._searchForNode(value)
|
||||
if self.right:
|
||||
found = found or self.right._searchForNode(value)
|
||||
return found
|
||||
return True # or self
|
||||
|
||||
found = False # or False, thats diff from BST
|
||||
if self.left:
|
||||
found = self.left._search(value)
|
||||
|
||||
if self.right:
|
||||
found = found or self.right._search(value)
|
||||
|
||||
return found
|
||||
|
||||
|
||||
def _isLeaf(self):
|
||||
return not self.right and not self.left
|
||||
|
||||
|
||||
def _getMaxHeight(self):
|
||||
''' Get the max height at the node, O(n)'''
|
||||
levelr, levell = 0, 0
|
||||
if self.right:
|
||||
levelr = self.right._getMaxHeight() + 1
|
||||
if self.left:
|
||||
levell = self.left._getMaxHeight() + 1
|
||||
return max(levelr, levell)
|
||||
|
||||
|
||||
def _getMinHeight(self, level=0):
|
||||
''' Get the min height at the node, O(n)'''
|
||||
levelr, levell = -1, -1
|
||||
if self.right:
|
||||
levelr = self.right._getMinHeight(level +1)
|
||||
if self.left:
|
||||
levell = self.left._getMinHeight(level +1)
|
||||
return min(levelr, levell) + 1
|
||||
|
||||
|
||||
def _isBalanced(self):
|
||||
''' Find whether the tree is balanced, by calculating heights first, O(n2) '''
|
||||
if self._getMaxHeight() - self._getMinHeight() < 2:
|
||||
return False
|
||||
else:
|
||||
if self._isLeaf():
|
||||
return True
|
||||
elif self.left and self.right:
|
||||
return self.left._isBalanced() and self.right._isBalanced()
|
||||
elif not self.left and self.right:
|
||||
return self.right._isBalanced()
|
||||
elif not self.right and self.left:
|
||||
return self.left._isBalanced()
|
||||
|
||||
def _isBST(self, mintree=None, maxtree=None):
|
||||
''' Find whether the tree is a BST, inorder '''
|
||||
if self.item:
|
||||
if not mintree:
|
||||
mintree = self.item
|
||||
if not maxtree:
|
||||
maxtree = self.item
|
||||
|
||||
if self._isLeaf():
|
||||
return True
|
||||
elif self.left:
|
||||
if self.left.item < self.item and mintree > self.left.item:
|
||||
mintree = self.left.item
|
||||
return self.left._isBST(mintree, maxtree)
|
||||
else:
|
||||
return False
|
||||
elif self.right:
|
||||
if self.right.item > self.item and maxtree < self.right.item:
|
||||
maxtree = self.right.item
|
||||
return self.right._isBST(mintree, maxtree)
|
||||
else:
|
||||
return False
|
||||
else:
|
||||
print('Tree is empty')
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class BinaryTree(object):
|
||||
class BT(object):
|
||||
|
||||
def __init__(self):
|
||||
self.root = None
|
||||
|
||||
|
||||
def addNode(self, value):
|
||||
def add(self, value):
|
||||
if not self.root:
|
||||
self.root = NodeBT(value)
|
||||
self.root = Node(value)
|
||||
else:
|
||||
self.root._addNextNode(value)
|
||||
self.root._add(value)
|
||||
|
||||
|
||||
def isLeaf(self, value):
|
||||
node = self.root._searchForNode(value)
|
||||
if node:
|
||||
return node._isLeaf()
|
||||
else:
|
||||
print "Node not found."
|
||||
|
||||
|
||||
def getNodeLevel(self, item):
|
||||
node = self.root._searchForNode(item)
|
||||
if node:
|
||||
return node.level
|
||||
else:
|
||||
print('Node not found')
|
||||
|
||||
|
||||
def isRoot(self, value):
|
||||
return self.root.item == value
|
||||
|
||||
|
||||
def getHeight(self):
|
||||
return self.root._getMaxHeight()
|
||||
|
||||
|
||||
def isBalanced(self):
|
||||
return self.root._isBalanced()
|
||||
|
||||
|
||||
def isBST(self):
|
||||
return self.root._isBST()
|
||||
|
||||
|
||||
def preorder(self):
|
||||
def printPreorder(self):
|
||||
current = self.root
|
||||
nodes, stack = [], []
|
||||
while stack or current:
|
||||
if current:
|
||||
nodes.append(current.item) # thats what change
|
||||
nodes.append(current.item) # this is what change
|
||||
stack.append(current)
|
||||
current = current.left
|
||||
else:
|
||||
current = stack.pop()
|
||||
current = current.right
|
||||
return nodes
|
||||
print nodes
|
||||
|
||||
|
||||
def printInorder(self):
|
||||
current = self.root
|
||||
nodes, stack = [], []
|
||||
while stack or current:
|
||||
|
||||
if current:
|
||||
stack.append(current)
|
||||
current = current.left
|
||||
else:
|
||||
current = stack.pop()
|
||||
nodes.append(current.item) # this is what change
|
||||
current = current.right
|
||||
print nodes
|
||||
|
||||
|
||||
def search(self, value):
|
||||
if self.root:
|
||||
return self.root._search(value)
|
||||
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
bt = BinaryTree()
|
||||
|
||||
bt = BT()
|
||||
print "Adding nodes 1 to 10 in the tree..."
|
||||
for i in range(1, 10):
|
||||
bt.addNode(i)
|
||||
print "Is 8 a leaf? ", bt.isLeaf(8)
|
||||
print "Whats the level of node 8? ", bt.getNodeLevel(8)
|
||||
print "Is node 10 a root? ", bt.isRoot(10)
|
||||
print "Is node 1 a root? ", bt.isRoot(1)
|
||||
print "Whats the tree height? ", bt.getHeight()
|
||||
print "Is this tree BST? ", bt.isBST()
|
||||
print "Is this tree balanced? ", bt.isBalanced()
|
||||
print (bt.preorder())
|
||||
for i in range(1, 11):
|
||||
bt.add(i)
|
||||
|
||||
print
|
||||
print "Searching for nodes 16 and 6"
|
||||
print bt.search(16)
|
||||
print bt.search(6)
|
||||
|
||||
print
|
||||
print "Printing preorder..."
|
||||
bt.printPreorder()
|
||||
|
||||
print "Printing Inorder..."
|
||||
bt.printInorder()
|
Loading…
Add table
Add a link
Reference in a new issue