mirror of
https://github.com/autistic-symposium/master-algorithms-py.git
synced 2025-04-29 20:26:07 -04:00
fix few details, stacks
This commit is contained in:
parent
dffd4fb2b7
commit
5a7a97b25f
173
src/trees/binary_trees_and_others/binary_tree.py
Normal file
173
src/trees/binary_trees_and_others/binary_tree.py
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
#!/usr/bin/python
|
||||||
|
|
||||||
|
__author__ = "Mari Wahl"
|
||||||
|
__email__ = "marina.w4hl@gmail.com"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
''' Implementation of a binary tree and its properties. For example, the following bt:
|
||||||
|
|
||||||
|
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)
|
||||||
|
if not self.item:
|
||||||
|
self.item = new_node
|
||||||
|
elif not self.left:
|
||||||
|
self.left = new_node
|
||||||
|
elif not self.right:
|
||||||
|
self.right = new_node
|
||||||
|
else:
|
||||||
|
self.left = self.left._addNextNode(value, level_here+1)
|
||||||
|
return self
|
||||||
|
|
||||||
|
|
||||||
|
def _searchForNode(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
|
||||||
|
|
||||||
|
|
||||||
|
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):
|
||||||
|
''' Find whether the tree is a BST, inorder '''
|
||||||
|
if self.item:
|
||||||
|
if self._isLeaf():
|
||||||
|
return True
|
||||||
|
elif self.left:
|
||||||
|
if self.left.item < self.item:
|
||||||
|
return self.left._isBST()
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
elif self.right:
|
||||||
|
if self.right.item > self.item:
|
||||||
|
return self.right._isBST()
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
raise Exception('Tree is empty')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class BinaryTree(object):
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.root = None
|
||||||
|
|
||||||
|
|
||||||
|
def addNode(self, value):
|
||||||
|
if not self.root:
|
||||||
|
self.root = NodeBT(value)
|
||||||
|
else:
|
||||||
|
self.root._addNextNode(value)
|
||||||
|
|
||||||
|
|
||||||
|
def isLeaf(self, value):
|
||||||
|
node = self.root._searchForNode(value)
|
||||||
|
return node._isLeaf()
|
||||||
|
|
||||||
|
def getNodeLevel(self, item):
|
||||||
|
node = self.root._searchForNode(item)
|
||||||
|
if node:
|
||||||
|
return node.level
|
||||||
|
else:
|
||||||
|
raise Exception('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()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
bt = BinaryTree()
|
||||||
|
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()
|
64
src/trees/binary_trees_and_others/binary_tree_lists.py
Normal file
64
src/trees/binary_trees_and_others/binary_tree_lists.py
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
#!/usr/bin/python
|
||||||
|
|
||||||
|
__author__ = "Mari Wahl"
|
||||||
|
__email__ = "marina.w4hl@gmail.com"
|
||||||
|
|
||||||
|
|
||||||
|
''' constructs a list with a root and 2 empty sublists for the children. To add a left subtree to the root of a tree, we need to insert a new list into the second position of the root list '''
|
||||||
|
|
||||||
|
|
||||||
|
def BinaryTreeList(r):
|
||||||
|
return [r, [], []]
|
||||||
|
|
||||||
|
|
||||||
|
def insertLeft(root, newBranch):
|
||||||
|
t = root.pop(1)
|
||||||
|
if len(t) > 1:
|
||||||
|
root.insert(1,[newBranch,t,[]])
|
||||||
|
else:
|
||||||
|
root.insert(1,[newBranch, [], []])
|
||||||
|
return root
|
||||||
|
|
||||||
|
|
||||||
|
def insertRight(root, newBranch):
|
||||||
|
t = root.pop(2)
|
||||||
|
if len(t) > 1:
|
||||||
|
root.insert(2,[newBranch,[],t])
|
||||||
|
else:
|
||||||
|
root.insert(2,[newBranch,[],[]])
|
||||||
|
return root
|
||||||
|
|
||||||
|
def getRootVal(root):
|
||||||
|
return root[0]
|
||||||
|
|
||||||
|
def setRootVal(root, newVal):
|
||||||
|
root[0] = newVal
|
||||||
|
|
||||||
|
def getLeftChild(root):
|
||||||
|
return root[1]
|
||||||
|
|
||||||
|
def getRightChild(root):
|
||||||
|
return root[2]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
'''
|
||||||
|
3
|
||||||
|
[5, [4, [], []], []]
|
||||||
|
[7, [], [6, [], []]]
|
||||||
|
'''
|
||||||
|
|
||||||
|
r = BinaryTreeList(3)
|
||||||
|
insertLeft(r,4)
|
||||||
|
insertLeft(r,5)
|
||||||
|
insertRight(r,6)
|
||||||
|
insertRight(r,7)
|
||||||
|
print(getRootVal(r))
|
||||||
|
print(getLeftChild(r))
|
||||||
|
print(getRightChild(r))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
|
|
@ -1,13 +1,13 @@
|
|||||||
#!/usr/bin/python3
|
#!/usr/bin/python
|
||||||
# mari von steinkirch @2013
|
|
||||||
# steinkirch at gmail
|
|
||||||
|
|
||||||
|
__author__ = "Mari Wahl"
|
||||||
|
__email__ = "marina.w4hl@gmail.com"
|
||||||
|
|
||||||
class BunchClass(dict):
|
class BunchClass(dict):
|
||||||
def __init__(self, *args, **kwds):
|
def __init__(self, *args, **kwds):
|
||||||
super(BunchClass, self).__init__(*args, **kwds)
|
super(BunchClass, self).__init__(*args, **kwds)
|
||||||
self.__dict__ = self
|
self.__dict__ = self
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
''' {'right': {'right': 'Xander', 'left': 'Willow'}, 'left': {'right': 'Angel', 'left': 'Buffy'}}'''
|
''' {'right': {'right': 'Xander', 'left': 'Willow'}, 'left': {'right': 'Angel', 'left': 'Buffy'}}'''
|
||||||
@ -20,4 +20,4 @@ if __name__ == '__main__':
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,13 +1,16 @@
|
|||||||
#!/usr/bin/python3
|
#!/usr/bin/python
|
||||||
# mari von steinkirch @2013
|
|
||||||
# steinkirch at gmail
|
|
||||||
|
|
||||||
|
__author__ = "Mari Wahl"
|
||||||
|
__email__ = "marina.w4hl@gmail.com"
|
||||||
|
|
||||||
|
""" A class for a simple tree """
|
||||||
|
|
||||||
class SimpleTree(object):
|
class SimpleTree(object):
|
||||||
def __init__(self, value, children = None):
|
def __init__(self, value=None, children = None):
|
||||||
if children == None: children = []
|
self.value = value
|
||||||
self.children = children
|
self.children = children
|
||||||
self.value = value
|
if self.children == None:
|
||||||
|
self.children = []
|
||||||
|
|
||||||
def __repr__(self, level=0):
|
def __repr__(self, level=0):
|
||||||
ret = "\t"*level+repr(self.value)+"\n"
|
ret = "\t"*level+repr(self.value)+"\n"
|
||||||
@ -16,6 +19,7 @@ class SimpleTree(object):
|
|||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
"""
|
"""
|
||||||
'a'
|
'a'
|
@ -1,20 +1,20 @@
|
|||||||
#!/usr/bin/python3
|
#!/usr/bin/python
|
||||||
# mari von steinkirch 2013
|
|
||||||
# http://astro.sunysb.edu/steinkirch
|
__author__ = "Mari Wahl"
|
||||||
|
__email__ = "marina.w4hl@gmail.com"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
''' Implementation of a binary tree and its properties. For example, the following bt:
|
||||||
|
|
||||||
''' Implementation of a binary tree and its properties. For example, the following bt:
|
|
||||||
|
|
||||||
1 ---> level 0
|
1 ---> level 0
|
||||||
2 3 ---> level 1
|
2 3 ---> level 1
|
||||||
4 5 ---> level 2
|
4 5 ---> level 2
|
||||||
6 7 ---> level 3
|
6 7 ---> level 3
|
||||||
8 9 ---> level 4
|
8 9 ---> level 4
|
||||||
|
|
||||||
has the following properties:
|
has the following properties:
|
||||||
|
|
||||||
- SIZE OR NUMBER OF NODES: n = 9
|
- SIZE OR NUMBER OF NODES: n = 9
|
||||||
- NUMBER OF BRANCHES OR INTERNAL NODES: b = n-1 = 8
|
- NUMBER OF BRANCHES OR INTERNAL NODES: b = n-1 = 8
|
||||||
- VALUE OF ROOT = 1
|
- VALUE OF ROOT = 1
|
||||||
@ -35,13 +35,13 @@ class NodeBT(object):
|
|||||||
self.level = level
|
self.level = level
|
||||||
self.left = None
|
self.left = None
|
||||||
self.right = None
|
self.right = None
|
||||||
self.traversal = []
|
self.traversal = []
|
||||||
#self.parent = None # not used here but can be necessary for some problems
|
#self.parent = None # not used here but can be necessary for some problems
|
||||||
|
|
||||||
'''
|
'''
|
||||||
METHODS TO MODIFY NODES
|
METHODS TO MODIFY NODES
|
||||||
'''
|
'''
|
||||||
|
|
||||||
def _addNextNode(self, value, level_here=1):
|
def _addNextNode(self, value, level_here=1):
|
||||||
''' Aux for self.addNode(value)'''
|
''' Aux for self.addNode(value)'''
|
||||||
self.traversal = []
|
self.traversal = []
|
||||||
@ -53,27 +53,27 @@ class NodeBT(object):
|
|||||||
elif not self.right:
|
elif not self.right:
|
||||||
self.right = new_node
|
self.right = new_node
|
||||||
else:
|
else:
|
||||||
self.left = self.left._addNextNode(value, level_here+1)
|
self.left = self.left._addNextNode(value, level_here+1)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
'''
|
'''
|
||||||
METHODS TO PRINT/SHOW NODES' ATTRIBUTES
|
METHODS TO PRINT/SHOW NODES' ATTRIBUTES
|
||||||
'''
|
'''
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
''' Private method for this class'string representation'''
|
''' Private method for this class'string representation'''
|
||||||
return '{}'.format(self.item)
|
return '{}'.format(self.item)
|
||||||
|
|
||||||
def _getDFTpreOrder(self, node):
|
def _getDFTpreOrder(self, node):
|
||||||
''' Traversal Pre-Order, O(n)'''
|
''' Traversal Pre-Order, O(n)'''
|
||||||
if node:
|
if node:
|
||||||
if node.item: self.traversal.append(node.item)
|
if node.item: self.traversal.append(node.item)
|
||||||
self._getDFTpreOrder(node.left)
|
self._getDFTpreOrder(node.left)
|
||||||
self._getDFTpreOrder(node.right)
|
self._getDFTpreOrder(node.right)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def _printDFTpreOrder(self, noderoot):
|
def _printDFTpreOrder(self, noderoot):
|
||||||
''' Fill the pre-order traversal array '''
|
''' Fill the pre-order traversal array '''
|
||||||
self.traversal = []
|
self.traversal = []
|
||||||
@ -85,9 +85,9 @@ class NodeBT(object):
|
|||||||
if node:
|
if node:
|
||||||
self._getDFTinOrder(node.left)
|
self._getDFTinOrder(node.left)
|
||||||
if node.item: self.traversal.append(node.item)
|
if node.item: self.traversal.append(node.item)
|
||||||
self._getDFTinOrder(node.right)
|
self._getDFTinOrder(node.right)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def _printDFTinOrder(self, noderoot):
|
def _printDFTinOrder(self, noderoot):
|
||||||
''' Fill the in-order traversal array '''
|
''' Fill the in-order traversal array '''
|
||||||
self.traversal = []
|
self.traversal = []
|
||||||
@ -98,29 +98,29 @@ class NodeBT(object):
|
|||||||
''' Traversal post-Order, O(n)'''
|
''' Traversal post-Order, O(n)'''
|
||||||
if node:
|
if node:
|
||||||
self._getDFTpostOrder(node.left)
|
self._getDFTpostOrder(node.left)
|
||||||
self._getDFTpostOrder(node.right)
|
self._getDFTpostOrder(node.right)
|
||||||
if node.item: self.traversal.append(node.item)
|
if node.item: self.traversal.append(node.item)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def _getBFT(self, node):
|
def _getBFT(self, node):
|
||||||
''' Traversal bft, O(n)'''
|
''' Traversal bft, O(n)'''
|
||||||
if node:
|
if node:
|
||||||
queue = deque()
|
queue = deque()
|
||||||
queue.append(node)
|
queue.append(node)
|
||||||
while len(queue) > 0:
|
while len(queue) > 0:
|
||||||
current = queue.popleft()
|
current = queue.popleft()
|
||||||
if current.item: self.traversal.append(current)
|
if current.item: self.traversal.append(current)
|
||||||
if current.left: queue.append(current.left)
|
if current.left: queue.append(current.left)
|
||||||
if current.right: queue.append(current.right)
|
if current.right: queue.append(current.right)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def _printBFT(self, noderoot):
|
def _printBFT(self, noderoot):
|
||||||
''' Fill the in-order traversal array '''
|
''' Fill the in-order traversal array '''
|
||||||
self.traversal = []
|
self.traversal = []
|
||||||
self._getBFT(noderoot)
|
self._getBFT(noderoot)
|
||||||
return self.traversal
|
return self.traversal
|
||||||
|
|
||||||
|
|
||||||
def _printDFTpostOrder(self, noderoot):
|
def _printDFTpostOrder(self, noderoot):
|
||||||
''' Fill the post-order traversal array '''
|
''' Fill the post-order traversal array '''
|
||||||
self.traversal = []
|
self.traversal = []
|
||||||
@ -132,14 +132,14 @@ class NodeBT(object):
|
|||||||
if self.item == value: return self
|
if self.item == value: return self
|
||||||
else:
|
else:
|
||||||
found = None
|
found = None
|
||||||
if self.left: found = self.left._searchForNode(value)
|
if self.left: found = self.left._searchForNode(value)
|
||||||
if self.right: found = found or self.right._searchForNode(value)
|
if self.right: found = found or self.right._searchForNode(value)
|
||||||
return found
|
return found
|
||||||
|
|
||||||
def _findNode(self, value):
|
def _findNode(self, value):
|
||||||
''' Find whether a node is in the tree.
|
''' Find whether a node is in the tree.
|
||||||
if the traversal was calculated, it is just a membership
|
if the traversal was calculated, it is just a membership
|
||||||
checking, which is O(1), otherwise it is necessary to traverse
|
checking, which is O(1), otherwise it is necessary to traverse
|
||||||
the binary tree, so best case is O(1) and worst is O(n). '''
|
the binary tree, so best case is O(1) and worst is O(n). '''
|
||||||
if self.traversal: return value in self.traversal
|
if self.traversal: return value in self.traversal
|
||||||
else: return self._searchForNode(value)
|
else: return self._searchForNode(value)
|
||||||
@ -154,8 +154,8 @@ class NodeBT(object):
|
|||||||
if self.right:
|
if self.right:
|
||||||
levelr = self.right._getMaxHeight() + 1
|
levelr = self.right._getMaxHeight() + 1
|
||||||
if self.left:
|
if self.left:
|
||||||
levell = self.left._getMaxHeight() + 1
|
levell = self.left._getMaxHeight() + 1
|
||||||
return max(levelr, levell)
|
return max(levelr, levell)
|
||||||
|
|
||||||
def _getMinHeight(self, level=0):
|
def _getMinHeight(self, level=0):
|
||||||
''' Get the min height at the node, O(n)'''
|
''' Get the min height at the node, O(n)'''
|
||||||
@ -163,9 +163,9 @@ class NodeBT(object):
|
|||||||
if self.right:
|
if self.right:
|
||||||
levelr = self.right._getMinHeight(level +1)
|
levelr = self.right._getMinHeight(level +1)
|
||||||
if self.left:
|
if self.left:
|
||||||
levell = self.left._getMinHeight(level +1)
|
levell = self.left._getMinHeight(level +1)
|
||||||
return min(levelr, levell) + 1
|
return min(levelr, levell) + 1
|
||||||
|
|
||||||
def _isBalanced(self):
|
def _isBalanced(self):
|
||||||
''' Find whether the tree is balanced, by calculating heights first, O(n2) '''
|
''' Find whether the tree is balanced, by calculating heights first, O(n2) '''
|
||||||
if self._getMaxHeight() - self._getMinHeight() < 2:
|
if self._getMaxHeight() - self._getMinHeight() < 2:
|
||||||
@ -174,14 +174,14 @@ class NodeBT(object):
|
|||||||
if self._isLeaf():
|
if self._isLeaf():
|
||||||
return True
|
return True
|
||||||
elif self.left and self.right:
|
elif self.left and self.right:
|
||||||
return self.left._isBalanced() and self.right._isBalanced()
|
return self.left._isBalanced() and self.right._isBalanced()
|
||||||
elif not self.left and self.right:
|
elif not self.left and self.right:
|
||||||
return self.right._isBalanced()
|
return self.right._isBalanced()
|
||||||
elif not self.right and self.left:
|
elif not self.right and self.left:
|
||||||
return self.right._isBalanced()
|
return self.right._isBalanced()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def _isBalancedImproved(self):
|
def _isBalancedImproved(self):
|
||||||
''' Find whehter the tree is balanced in each node, O(n) '''
|
''' Find whehter the tree is balanced in each node, O(n) '''
|
||||||
return 'To Be written'
|
return 'To Be written'
|
||||||
@ -190,37 +190,37 @@ class NodeBT(object):
|
|||||||
(1) Do an inorder, check if the inorder is sorted. However inorder
|
(1) Do an inorder, check if the inorder is sorted. However inorder
|
||||||
can't handle the difference between duplicate values on the left
|
can't handle the difference between duplicate values on the left
|
||||||
or on the right (if it is in the right, the tree is not bst).
|
or on the right (if it is in the right, the tree is not bst).
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
|
||||||
def _isBST(self):
|
def _isBST(self):
|
||||||
''' Find whether the tree is a BST, inorder '''
|
''' Find whether the tree is a BST, inorder '''
|
||||||
if self.item:
|
if self.item:
|
||||||
if self._isLeaf(): return True
|
if self._isLeaf(): return True
|
||||||
elif self.left:
|
elif self.left:
|
||||||
if self.left.item < self.item: return self.left._isBST()
|
if self.left.item < self.item: return self.left._isBST()
|
||||||
else: return False
|
else: return False
|
||||||
elif self.right:
|
elif self.right:
|
||||||
if self.right.item > self.item: return self.right._isBST()
|
if self.right.item > self.item: return self.right._isBST()
|
||||||
else: return False
|
else: return False
|
||||||
else:
|
else:
|
||||||
raise Exception('Tree is empty')
|
raise Exception('Tree is empty')
|
||||||
|
|
||||||
|
|
||||||
def _getAncestorBST(self, n1, n2):
|
def _getAncestorBST(self, n1, n2):
|
||||||
''' Return the ancestor of two nodes if it is a bst.
|
''' Return the ancestor of two nodes if it is a bst.
|
||||||
we are supposing the values in the tree are unique.'''
|
we are supposing the values in the tree are unique.'''
|
||||||
if n1 == self.item or n2 == self.item : return self.item
|
if n1 == self.item or n2 == self.item : return self.item
|
||||||
elif self.item < n1 and self.item < n2:
|
elif self.item < n1 and self.item < n2:
|
||||||
self.right.getAncestorBST(n1, n2)
|
self.right.getAncestorBST(n1, n2)
|
||||||
elif self.item > n1 and self.item > n2:
|
elif self.item > n1 and self.item > n2:
|
||||||
self.left.getAncestorBST(n1, n2)
|
self.left.getAncestorBST(n1, n2)
|
||||||
else:
|
else:
|
||||||
return self.item
|
return self.item
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class BinaryTree(object):
|
class BinaryTree(object):
|
||||||
'''
|
'''
|
||||||
>>> bt = BinaryTree()
|
>>> bt = BinaryTree()
|
||||||
@ -270,30 +270,30 @@ class BinaryTree(object):
|
|||||||
>>> bt.getAncestor(8, 5, 'post-in')
|
>>> bt.getAncestor(8, 5, 'post-in')
|
||||||
2
|
2
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
''' Construtor for the Binary Tree, which is a container of Nodes'''
|
|
||||||
self.root = None
|
|
||||||
|
|
||||||
|
|
||||||
'''
|
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
''' Constructor for the Binary Tree, which is a container of Nodes'''
|
||||||
|
self.root = None
|
||||||
|
|
||||||
|
|
||||||
|
'''
|
||||||
METHODS TO MODIFY THE TREE
|
METHODS TO MODIFY THE TREE
|
||||||
'''
|
'''
|
||||||
|
|
||||||
def addNode(self, value):
|
def addNode(self, value):
|
||||||
''' Add new node to the tree, by the left first, O(n) '''
|
''' Add new node to the tree, by the left first, O(n) '''
|
||||||
if not self.root: self.root = NodeBT(value)
|
if not self.root: self.root = NodeBT(value)
|
||||||
else: self.root._addNextNode(value)
|
else: self.root._addNextNode(value)
|
||||||
|
|
||||||
'''
|
'''
|
||||||
METHODS TO PRINT/SHOW TREES' ATTRIBUTES
|
METHODS TO PRINT/SHOW TREES' ATTRIBUTES
|
||||||
'''
|
'''
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
''' Private method for this class'string representation'''
|
''' Private method for this class'string representation'''
|
||||||
return '{}'.format(self.item)
|
return '{}'.format(self.item)
|
||||||
|
|
||||||
def printTree(self, order = 'pre'):
|
def printTree(self, order = 'pre'):
|
||||||
''' Print Tree in the chosen order '''
|
''' Print Tree in the chosen order '''
|
||||||
@ -301,53 +301,53 @@ class BinaryTree(object):
|
|||||||
if order == 'pre': return self.root._printDFTpreOrder(self.root)
|
if order == 'pre': return self.root._printDFTpreOrder(self.root)
|
||||||
elif order == 'in': return self.root._printDFTinOrder(self.root)
|
elif order == 'in': return self.root._printDFTinOrder(self.root)
|
||||||
elif order == 'post': return self.root._printDFTpostOrder(self.root)
|
elif order == 'post': return self.root._printDFTpostOrder(self.root)
|
||||||
elif order == 'bft': return self.root._printBFT(self.root)
|
elif order == 'bft': return self.root._printBFT(self.root)
|
||||||
else: raise Exception('Tree is empty')
|
else: raise Exception('Tree is empty')
|
||||||
|
|
||||||
def hasNode(self, value):
|
def hasNode(self, value):
|
||||||
''' Verify whether the node is in the Tree '''
|
''' Verify whether the node is in the Tree '''
|
||||||
return bool(self.root._findNode(value))
|
return bool(self.root._findNode(value))
|
||||||
|
|
||||||
def isLeaf(self, value):
|
def isLeaf(self, value):
|
||||||
''' Return True if the node is a Leaf '''
|
''' Return True if the node is a Leaf '''
|
||||||
node = self.root._searchForNode(value)
|
node = self.root._searchForNode(value)
|
||||||
return node._isLeaf()
|
return node._isLeaf()
|
||||||
|
|
||||||
def getNodeLevel(self, item):
|
def getNodeLevel(self, item):
|
||||||
''' Return the level of the node, best O(1), worst O(n) '''
|
''' Return the level of the node, best O(1), worst O(n) '''
|
||||||
node = self.root._searchForNode(item)
|
node = self.root._searchForNode(item)
|
||||||
if node: return node.level
|
if node: return node.level
|
||||||
else: raise Exception('Node not found')
|
else: raise Exception('Node not found')
|
||||||
|
|
||||||
def getSizeTree(self):
|
def getSizeTree(self):
|
||||||
''' Return how many nodes in the tree, O(n) '''
|
''' Return how many nodes in the tree, O(n) '''
|
||||||
return len(self.root._printDFTpreOrder(self.root))
|
return len(self.root._printDFTpreOrder(self.root))
|
||||||
|
|
||||||
def isRoot(self, value):
|
def isRoot(self, value):
|
||||||
'''Return the root of the tree '''
|
'''Return the root of the tree '''
|
||||||
return self.root.item == value
|
return self.root.item == value
|
||||||
|
|
||||||
def getHeight(self):
|
def getHeight(self):
|
||||||
''' Returns the height/depth of the tree, best/worst O(n) '''
|
''' Returns the height/depth of the tree, best/worst O(n) '''
|
||||||
return self.root._getMaxHeight()
|
return self.root._getMaxHeight()
|
||||||
|
|
||||||
def isBalanced(self, method=1):
|
def isBalanced(self, method=1):
|
||||||
''' Return True if the tree is balanced'''
|
''' Return True if the tree is balanced'''
|
||||||
if method == 1:
|
if method == 1:
|
||||||
''' O(n2)'''
|
''' O(n2)'''
|
||||||
return self.root._isBalanced()
|
return self.root._isBalanced()
|
||||||
else:
|
else:
|
||||||
''' O(n)'''
|
''' O(n)'''
|
||||||
return self.root._isBalancedImproved()
|
return self.root._isBalancedImproved()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
''' The followin methods are for searching the lowest common ancestor
|
|
||||||
|
''' The following methods are for searching the lowest common ancestor
|
||||||
in a BT. Since a simple BT does not have ordering, it can be O(n). If
|
in a BT. Since a simple BT does not have ordering, it can be O(n). If
|
||||||
we have a link for the ancestors, the steps are:
|
we have a link for the ancestors, the steps are:
|
||||||
(1) search both trees in order to find the nodes separately
|
(1) search both trees in order to find the nodes separately
|
||||||
(2) list all ancestors
|
(2) list all ancestors
|
||||||
(3) find first that mach
|
(3) find first that mach
|
||||||
obs: if we do this too many times we can do a pre and use the methods here'''
|
obs: if we do this too many times we can do a pre and use the methods here'''
|
||||||
|
|
||||||
def isBST(self, method=1):
|
def isBST(self, method=1):
|
||||||
@ -365,12 +365,12 @@ class BinaryTree(object):
|
|||||||
preorder = preorder[1:]
|
preorder = preorder[1:]
|
||||||
i = 0
|
i = 0
|
||||||
item = inorder[0]
|
item = inorder[0]
|
||||||
value1left, value2left = False, False
|
value1left, value2left = False, False
|
||||||
while item != root and i < len(inorder):
|
while item != root and i < len(inorder):
|
||||||
if item == value1: value1left = True
|
if item == value1: value1left = True
|
||||||
elif item == value2: value2left = True
|
elif item == value2: value2left = True
|
||||||
i += 1
|
i += 1
|
||||||
item = inorder[i]
|
item = inorder[i]
|
||||||
if (value1left and not value2left) or (value2left and not value1left):
|
if (value1left and not value2left) or (value2left and not value1left):
|
||||||
return root
|
return root
|
||||||
else:
|
else:
|
||||||
@ -380,44 +380,44 @@ class BinaryTree(object):
|
|||||||
''' Return the ancestor of two nodes with pre and post'''
|
''' Return the ancestor of two nodes with pre and post'''
|
||||||
root = preorder[0]
|
root = preorder[0]
|
||||||
preorder = preorder[1:]
|
preorder = preorder[1:]
|
||||||
postorder = postorder[:-1]
|
postorder = postorder[:-1]
|
||||||
value1right, value2right = False, False
|
value1right, value2right = False, False
|
||||||
i = len(postorder)-1
|
i = len(postorder)-1
|
||||||
itempre = preorder[0]
|
itempre = preorder[0]
|
||||||
itempos = postorder[i]
|
itempos = postorder[i]
|
||||||
while itempre != itempos and i > 0:
|
while itempre != itempos and i > 0:
|
||||||
if itempos == value1: value1right = True
|
if itempos == value1: value1right = True
|
||||||
elif itempos == value2: value2right = True
|
elif itempos == value2: value2right = True
|
||||||
i -= 1
|
i -= 1
|
||||||
itempos = postorder[i]
|
itempos = postorder[i]
|
||||||
|
|
||||||
if (value1right and not value2right) or (value2right and not value1right):
|
if (value1right and not value2right) or (value2right and not value1right):
|
||||||
return root
|
return root
|
||||||
else:
|
else:
|
||||||
return self._getAncestorPrePost(preorder, postorder[:i] + postorder[i+1:], value1, value2)
|
return self._getAncestorPrePost(preorder, postorder[:i] + postorder[i+1:], value1, value2)
|
||||||
|
|
||||||
def _getAncestorInPost(self, inorder, postorder, value1, value2):
|
def _getAncestorInPost(self, inorder, postorder, value1, value2):
|
||||||
''' Return the ancestor of two nodes with in and post'''
|
''' Return the ancestor of two nodes with in and post'''
|
||||||
root = postorder[-1]
|
root = postorder[-1]
|
||||||
postorder = postorder[:-1]
|
postorder = postorder[:-1]
|
||||||
value1left, value2left = False, False
|
value1left, value2left = False, False
|
||||||
i = 0
|
i = 0
|
||||||
item = inorder[i]
|
item = inorder[i]
|
||||||
while item != root and i < len(inorder):
|
while item != root and i < len(inorder):
|
||||||
if item == value1: value1left = True
|
if item == value1: value1left = True
|
||||||
elif item == value2: value2left = True
|
elif item == value2: value2left = True
|
||||||
i += 1
|
i += 1
|
||||||
item = inorder[i]
|
item = inorder[i]
|
||||||
|
|
||||||
if (value1left and not value2left) or (value2left and not value1left):
|
if (value1left and not value2left) or (value2left and not value1left):
|
||||||
return root
|
return root
|
||||||
else:
|
else:
|
||||||
return self._getAncestorInPost(postorder, inorder[:i] + inorder[i+1:], value1, value2)
|
return self._getAncestorInPost(postorder, inorder[:i] + inorder[i+1:], value1, value2)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def _getAncestorBST2(self, preorder, value1, value2):
|
def _getAncestorBST2(self, preorder, value1, value2):
|
||||||
''' Return the ancestor of two nodes if it is a bst, using traversal'''
|
''' Return the ancestor of two nodes if it is a bst, using traversal'''
|
||||||
while preorder:
|
while preorder:
|
||||||
@ -430,35 +430,35 @@ class BinaryTree(object):
|
|||||||
except: return current
|
except: return current
|
||||||
elif value1 <= current <= value2:
|
elif value1 <= current <= value2:
|
||||||
return current
|
return current
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def getAncestor(self, value1, value2, method='pre-in'):
|
def getAncestor(self, value1, value2, method='pre-in'):
|
||||||
''' Return the commom ancestor for two nodes'''
|
''' Return the commom ancestor for two nodes'''
|
||||||
if method == 'pre-in':
|
if method == 'pre-in':
|
||||||
''' Using pre and inorder, best/worst O(n)'''
|
''' Using pre and inorder, best/worst O(n)'''
|
||||||
preorder = self.root._printDFTpreOrder(self.root)
|
preorder = self.root._printDFTpreOrder(self.root)
|
||||||
inorder = self.root._printDFTinOrder(self.root)
|
inorder = self.root._printDFTinOrder(self.root)
|
||||||
return self._getAncestorPreIn(preorder, inorder, value1, value2)
|
return self._getAncestorPreIn(preorder, inorder, value1, value2)
|
||||||
if method == 'pre-post':
|
if method == 'pre-post':
|
||||||
''' Using pre and postorder, best/worst O(n)'''
|
''' Using pre and postorder, best/worst O(n)'''
|
||||||
preorder = self.root._printDFTpreOrder(self.root)
|
preorder = self.root._printDFTpreOrder(self.root)
|
||||||
postorder = self.root._printDFTpostOrder(self.root)
|
postorder = self.root._printDFTpostOrder(self.root)
|
||||||
return self._getAncestorPrePost(preorder, postorder, value1, value2)
|
return self._getAncestorPrePost(preorder, postorder, value1, value2)
|
||||||
if method == 'post-in':
|
if method == 'post-in':
|
||||||
''' Using in and postorder, best/worst O(n)'''
|
''' Using in and postorder, best/worst O(n)'''
|
||||||
inorder = self.root._printDFTinOrder(self.root)
|
inorder = self.root._printDFTinOrder(self.root)
|
||||||
postorder = self.root._printDFTpostOrder(self.root)
|
postorder = self.root._printDFTpostOrder(self.root)
|
||||||
return self._getAncestorInPost(inorder, postorder, value1, value2)
|
return self._getAncestorInPost(inorder, postorder, value1, value2)
|
||||||
if method == 'bst':
|
if method == 'bst':
|
||||||
if self.isBST():
|
if self.isBST():
|
||||||
return self.root._getAncestorBST(value1, value2)
|
return self.root._getAncestorBST(value1, value2)
|
||||||
|
|
||||||
#preorder = self.root._printDFTpreOrder(self.root)
|
#preorder = self.root._printDFTpreOrder(self.root)
|
||||||
#return self._getAncestorBST2(preorder, value1, value2)
|
#return self._getAncestorBST2(preorder, value1, value2)
|
||||||
else:
|
else:
|
||||||
return Exception('The tree is not a BST')
|
return Exception('The tree is not a BST')
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
import doctest
|
import doctest
|
||||||
doctest.testmod()
|
doctest.testmod()
|
Loading…
x
Reference in New Issue
Block a user