fix few details, binary search trees

This commit is contained in:
Mari Wahl 2014-08-27 21:14:22 -04:00
parent 5a7a97b25f
commit f77b8eaaf2
15 changed files with 73 additions and 629 deletions

Binary file not shown.

View File

@ -1,68 +0,0 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
from BT import BT
class BST(BT):
def __init__(self, value=None):
self.value = value
self.left = None
self.right = None
def insert_left(self, new_node):
self.insert(value)
def insert_right(self, new_node):
self.insert(value)
def insert(self, value):
if self.value == None:
self.value = value
else:
if value > self.value:
self.right = self.right and self.right.insert(value) or BST(value)
else:
self.left = self.left and self.left.insert(value) or BST(value)
return self
def find(self, value):
if value == self.value:
return self
elif value > self.value and self.right:
return self.right.find(value)
elif self.left:
return self.left.find(value)
return None
def main():
"""
BST
4
2 6
1 3 5 7
"""
tree = BST()
tree.insert(4)
tree.insert(2)
tree.insert(6)
tree.insert(1)
tree.insert(3)
tree.insert(7)
tree.insert(5)
print(tree.get_right())
print(tree.get_right().get_left())
print(tree.get_right().get_right())
print(tree.get_left())
print(tree.get_left().get_left())
print(tree.get_left().get_right() == 1)
assert(tree.find(30) == None)
if __name__ == '__main__':
main()

View File

@ -1,66 +0,0 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
class Node(object):
def __init__(self, value):
self.value = value
self.left = None
self.right = None
def __repr__(self):
return '{}'.format(self.value)
class BSTwithNodes(object):
def __init__(self):
self.root = None
def insert(self, value):
if self.root == None:
self.root = Node(value)
else:
current = self.root
while True:
if value < current.value:
if current.left:
current = current.left
else:
current.left = Node(value)
break;
elif value > current.value:
if current.right:
current = current.right
else:
current.right = Node(value)
break;
else:
break
def main():
"""
BST
4
2 6
1 3 5 7
"""
tree = BSTwithNodes()
l1 = [4, 2, 6, 1, 3, 7, 5]
for i in l1: tree.insert(i)
print(tree.root)
print(tree.root.right)
print(tree.root.right.left)
print(tree.root.right.right)
print(tree.root.left)
print(tree.root.left.left)
print(tree.root.left.right)
if __name__ == '__main__':
main()

View File

@ -1,72 +0,0 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
class BT(object):
def __init__(self, value):
self.value = value
self.left = None
self.right = None
def get_right(self):
return self.right
def get_left(self):
return self.left
def is_leaf(self):
return self.left is None and self.right is None
def set_root(self, obj):
self.value = obj
def get_root(self):
return self.value
def insert_left(self, new_node):
if self.left == None:
self.left = BT(new_node)
else:
t = BT(self.left)
t.left = new_node
self.left = t
def insert_right(self, new_node):
if self.right == None:
self.right = BT(new_node)
else:
t = BT(self.right)
t.right = new_node
self.right = t
def __repr__(self):
return '{}'.format(self.value)
def tests_BT():
"""
1
2 3
4 5 6 7
"""
tree = BT(1)
tree.insert_left(2)
tree.insert_right(3)
tree.get_left().insert_left(4)
tree.get_left().insert_right(5)
tree.get_right().insert_left(6)
tree.get_right().insert_right(7)
print(tree.get_right().get_right())
tree.get_right().get_right().set_root(8)
print(tree.get_right().get_right())
assert(tree.get_right().is_leaf() == False)
assert(tree.get_right().get_right().is_leaf() == True)
print("Tests Passed!")
if __name__ == '__main__':
tests_BT()

View File

@ -1,61 +0,0 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
def BinaryTreeList(r):
''' 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 '''
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()

View File

@ -1,140 +0,0 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
from BST_with_Nodes import BSTwithNodes, Node
class AVL(BSTwithNodes):
"""AVL binary search tree implementation.
Supports insert, find, and delete-min operations in O(lg n) time.
"""
def __init__(self):
self.root = None
def left_rotate(self, x):
y = x.right
y.value = x.value
if y.value is None:
self.root = y
else:
if y.value.left is x:
y.value.left = y
elif y.value.right is x:
y.value.right = y
x.right = y.left
if x.right is not None:
x.right.value = x
y.left = x
x.value = y
update_height(x)
update_height(y)
def right_rotate(self, x):
y = x.left
y.value = x.value
if y.value is None:
self.root = y
else:
if y.value.left is x:
y.value.left = y
elif y.value.right is x:
y.value.right = y
x.left = y.right
if x.left is not None:
x.left.value = x
y.right = x
x.value = y
update_height(x)
update_height(y)
def insert_item(self, value):
if self.root == None:
self.root = Node(value)
else:
current = self.root
while True:
if value < current.value:
if current.left:
current = current.left
else:
current.left = Node(value)
break;
elif value > current.value:
if current.right:
current = current.right
else:
current.right = Node(value)
break;
else:
break
def insert(self, value):
node = self.insert_item(value)
self.rebalance(node)
def rebalance(self, node):
while node is not None:
update_height(node)
if height(node.left) >= 2 + height(node.right):
if height(node.left.left) >= height(node.left.right):
self.right_rotate(node)
else:
self.left_rotate(node.left)
self.right_rotate(node)
elif height(node.right) >= 2 + height(node.left):
if height(node.right.right) >= height(node.right.left):
self.left_rotate(node)
else:
self.right_rotate(node.right)
self.left_rotate(node)
node = node.value
def inorder(self, node):
if node is not None:
self.inorder(node.left)
print(node.value)
self.inorder(node.right)
def preorder(self, node):
if node is not None:
print(node.value)
self.preorder(node.left)
self.preorder(node.right)
def postorder(self, node):
if node is not None:
self.postorder(node.left)
self.postorder(node.right)
print(node.value)
def height(node):
if node is None: return -1
else: return node.height
def update_height(node):
node.height = max(height(node.left), height(node.right)) + 1
def main():
tree = AVL()
tree.insert(4)
tree.insert(2)
tree.insert(6)
tree.insert(1)
tree.insert(3)
tree.insert(7)
tree.insert(5)
print('Inorder Traversal:')
tree.inorder(tree.root)
if __name__ == '__main__':
main()

View File

@ -1,102 +0,0 @@
#!/usr/bin/python3
# mari von steinkirch 2013
from binary_tree import BinaryTree, NodeBT
''' Implementation of a binary search tree and its properties.
We use the Binary Tree class and its Node class as superclasses, and we modify the methods
that are needeed to create a BST (polymorphism). For example, the following bst:
7 ---> level 0
4 9 ---> level 1
2 5 8 10 ---> level 2
1 6 ---> level 3
has the following properties:
- SIZE OR NUMBER OF NODES: n = 10
- NUMBER OF BRANCHES OR INTERNAL NODES: b = n-1 = 9
- VALUE OF ROOT = 7
- MAX_DEPTH OR HEIGHT: h = 3
- IS BALANCED? YES
- IS BST? YES
- INORDER DFT: 1, 2, 4, 5, 6, 7, 8, 9, 10
- POSTORDER DFT: 1, 2, 6, 5, 4, 8, 10, 9, 7
- PREORDER DFT: 7, 4, 2, 1, 5, 6, 9, 8, 10
- BFT: 7, 4, 9, 2, 5, 8, 10, 1, 6
'''
class NodeBST(NodeBT):
def _addNextNode(self, value, level_here=1):
''' Aux for self.addNode(value): for BST, best O(1), worst O(log n) '''
self.traversal = []
new_node = NodeBST(value, level_here)
if not self.item:
self.item = new_node
elif value < self.item:
self.left = self.left and self.left._addNextNode(value, level_here+1) or new_node
else:
self.right = self.right and self.right._addNextNode(value, level_here+1) or new_node
return self
def _searchForNode(self, value):
''' Traverse the tree looking for the node. For BST it is O(logn) if the
tree is balanced, otherwise it can be O(n) '''
if self.item == value: return self
elif value > self.item and self.right: return self.right._findNode(value)
elif value < self.item and self.left: return self.left._findNode(value)
return None
class BinarySearchTree(BinaryTree):
'''
>>> bst = BinarySearchTree()
>>> l1 = [7, 4, 5, 9, 2, 8, 1, 6, 10]
>>> for i in l1: bst.addNode(i)
>>> bst.hasNode(3)
False
>>> bst.hasNode(10)
True
>>> bst.printTree('pre')
[7, 4, 2, 1, 5, 6, 9, 8, 10]
>>> bst.printTree('post')
[1, 2, 6, 5, 4, 8, 10, 9, 7]
>>> bst.printTree('in')
[1, 2, 4, 5, 6, 7, 8, 9, 10]
>>> bst.printTree('bft')
[7, 4, 9, 2, 5, 8, 10, 1, 6]
>>> bst.getHeight()
3
>>> bst.isBST()
True
>>> bst.isBalanced()
False
>>> bst.isBalanced(2)
False
>>> bst.getAncestor(2, 9)
7
>>> bst.getAncestor(2, 9, 'bst')
7
>>> bst.getAncestor(2, 9, 'pre-post')
7
>>> bst.getAncestor(2, 9, 'post-in')
7
'''
def addNode(self, value):
''' Add new node to the tree, by the left first, O(n).
The only difference from the Binary Tree class is the node class is
NodeBST and not NodeBT '''
if not self.root: self.root = NodeBST(value)
else: self.root._addNextNode(value)
if __name__ == '__main__':
import doctest
doctest.testmod()

View File

@ -1,56 +0,0 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
from BT import BT
def is_bst(root, min=float('-inf'), max=float('inf')):
left, right, value = root.left, root.right, root.value
if min < value < max:
if left and right:
return is_bst(left, min, value) and is_bst(right, value, max)
elif left:
return is_bst(left, min, value)
elif right:
return is_bst(right, value, max)
return True
return False
def main():
"""
BST
4
2 6
1 3 5 7
BT
4
2 6
1 8 5 7
"""
bst = BT(4)
bst.insert_left(2)
bst.insert_right(6)
bst.get_left().insert_left(1)
bst.get_left().insert_right(3)
bst.get_right().insert_left(5)
bst.get_right().insert_right(7)
print('is_bst(bst) =', is_bst(bst))
bt = BT(4)
bt.insert_left(2)
bt.insert_right(6)
bt.get_left().insert_left(1)
bt.get_left().insert_right(8)
bt.get_right().insert_left(5)
bt.get_right().insert_right(7)
print('is_bst(bt) =', is_bst(bt))
if __name__ == '__main__':
main()

View File

@ -0,0 +1,73 @@
#!/usr/bin/python
__author__ = "Mari Wahl"
__email__ = "marina.w4hl@gmail.com"
from binary_tree import NodeBT, BinaryTree
class NodeBST(NodeBT):
def __init__(self, item=None, level=0):
self.item = item
self.level = level
self.left = None
self.right = None
def _addNextNode(self, value, level_here=1):
new_node = NodeBST(value, level_here)
if not self.item:
self.item = new_node
else:
if value > self.item:
self.right = self.right and self.right._addNextNode(value, level_here+1) or new_node
elif value < self.item:
self.left = self.left and self.left._addNextNode(value, level_here+1) or new_node
else:
print("BSTs do not support repeated items.")
return self # this is necessary!!!
def _searchForNode(self, value):
if self.item == value:
return self
elif self.left and value < self.item:
return self.left._searchForNode(value)
elif self.right and value > self.item:
return self.right._searchForNode(value)
else:
return False
class BinarySearchTree(BinaryTree):
def __init__(self):
self.root = None
def addNode(self, value):
if not self.root:
self.root = NodeBST(value)
else:
self.root._addNextNode(value)
if __name__ == '__main__':
bst = BinarySearchTree()
print "Adding nodes 1 to 10 in the tree..."
for i in range(1, 10):
bst.addNode(i)
print "Is 8 a leaf? ", bst.isLeaf(8)
print "Whats the level of node 8? ", bst.getNodeLevel(8)
print "Is node 10 a root? ", bst.isRoot(10)
print "Is node 1 a root? ", bst.isRoot(1)
print "Whats the tree height? ", bst.getHeight()
print "Is this tree BST? ", bst.isBST()
print "Is this tree balanced? ", bst.isBalanced()

View File

@ -1,64 +0,0 @@
#!/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()