Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
b29b801
updated init for AVL tree
Jakeand3rson Mar 10, 2015
a237012
added fuction to update height
Jakeand3rson Mar 10, 2015
8b18199
added fuction to rotate left
Jakeand3rson Mar 10, 2015
2a8f9c9
added fuction to rotate right
Jakeand3rson Mar 10, 2015
1d9b7ba
started balance function
Jakeand3rson Mar 10, 2015
5198433
added LL and LR rotation to balance function
Jakeand3rson Mar 10, 2015
b158ad3
added RR and RL rotation to balance function
Jakeand3rson Mar 10, 2015
a6fa30f
added RL rotation to balance function
Jakeand3rson Mar 10, 2015
6fec86a
updated function name to is_balanced
Jakeand3rson Mar 10, 2015
3bcee27
updated function name to is_balanced
Jakeand3rson Mar 10, 2015
3a255f1
added functions to find the left most and right most nodes to be used…
Mar 10, 2015
60ac702
added function to find the next node in the tree to be used for sort …
Mar 10, 2015
9939764
added function to find the previous node in tree. to be used in the s…
Mar 10, 2015
7b54d3f
corrected name for find_prev function
Mar 10, 2015
0949461
added function to sort tree after balance
Mar 10, 2015
b35d4b5
changed some naming, created in file test for sort
Mar 10, 2015
d0bd79d
added test for finding nodes, failing
Jakeand3rson Mar 10, 2015
7eccfc7
cleaned up name/main block and fixed linter error with variables
Jakeand3rson Mar 10, 2015
0441e14
added function to find node. used in sort function
Mar 10, 2015
d62b3ec
create function for hash table containing size count and order
Mar 12, 2015
44d4d13
added function to set data to check and set data to hash table
Mar 12, 2015
32b2349
created function for finding and returning hash data value
Mar 12, 2015
67c0e74
changed size
Jakeand3rson Mar 12, 2015
d3e9c56
wrote tests for hash, passing
Jakeand3rson Mar 12, 2015
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
207 changes: 206 additions & 1 deletion bst.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ def __init__(self, value, parent=None, left_child=None, right_child=None):
self.parent = parent
self.left = left_child
self.right = right_child
self.height = 0
self.balance = 0

def is_root(self):
'''Helper function for root node'''
Expand All @@ -23,6 +25,38 @@ def is_leaf(self):
''''Helper function for acknowledging leaf'''
return not (self.right_child or self.left_child)

def is_left(self):
'''Helper fuction for finding left child. Might be redundent with is_left
Will decide later........'''
if self.parent is None:
return self.parent
else:
return self is self.parent.left_child

def update_height(self, bubble_up=True):
'''If bubble_up is True, we go up the tree correcting height/balance
if not we will just correct the node'''
if self.left_child is None:
# set the left tree to zero
left_height = 0
else:
left_height = self.left_child.height + 1
if self.right_child is None:
# set the right tree to zero
right_height = 0
else:
right_height = self.right_child.height + 1
# we want to be able to balance even if we don't change the height

self.balance = left_height - right_height
height = max(left_height, right_height)
if self.height != height:
self.height = height
if self.parent is not None:
# We only bubble up if the height changes
if bubble_up:
self.parent.update_height()

def _get_dot(self):
"""recursively prepare a dot graph entry for this node."""
if self.left is not None:
Expand Down Expand Up @@ -112,7 +146,7 @@ def _depth(self, curr_depth, local_root):
r_depth = self._depth(curr_depth + 1, local_root.right)
return max(curr_depth, l_depth, r_depth)

def balance(self):
def is_balanced(self):
'''Return positive or negative integer to represent tree balance'''
ret_value = 0
if self.root is None:
Expand Down Expand Up @@ -216,6 +250,177 @@ def _descendants(leaf):
leaf.left = self._delete(val, leaf.left)
return leaf

def rotate_left(self, root):
left = root.is_left()
pivot = root.right_child

if pivot is None:
return
root.right_child = pivot.left_child
if pivot.left_child is not None:
root.right_child.parent = root
pivot.left_child = root
pivot.parent = root.parent
root.parent = pivot
if left is None:
self.root = pivot
elif left:
pivot.parent.left_child = pivot
else:
pivot.parent.right_child = pivot
root.update_height(False)
pivot.update_height(False)

def rotate_right(self, root):
left = root.is_left()
pivot = root.left_child
if pivot is None:
return
root.left_child = pivot.right_child
if pivot.right_child is not None:
root.left_child.parent = root
pivot.right_child = root
pivot.parent = root.parent
root.parent = pivot
if left is None:
self.root = pivot
elif left:
pivot.parent.left_child = pivot
else:
pivot.parent.right_child = pivot
root.update_height(False)
pivot.update_height(False)

def find_leftmost(self, node):
if node.left_child is None:
return node
else:
return self.find_leftmost(node.left_child)

def find_rightmost(self, node):
if node.right_child is None:
return node
else:
return self.find_rightmost(node.right_child)

def find_next(self, value):
node = self.find(value)
if (node is None) or (node.value != value):
return None
else:
right_child = node.right_child
if right_child is not None:
node = self.find_leftmost(right_child)
else:
parent = node.parent
while(parent is not None):
if node is parent.left_child:
break
node = parent
parent = node.parent
node = parent
if node is None:
return node
else:
return node.value

def find_prev(self, value):
node = self.find(value)
if (node is None) or (node.value != value):
return None
else:
left_child = node.left_child
if left_child is not None:
node = self.find_leftmost(left_child)
else:
parent = node.parent
while(parent is not None):
if node is parent.right_child:
break
node = parent
parent = node.parent
node = parent
if node is None:
return node
else:
return node.value

def find(self, value, node=None):
if node is None:
node = self.root
if self.root is None:
return None
else:
return self.find(value, self.root)
elif node.value == value:
return node
elif value < node.value:
if node.left_child is None:
return node
else:
return self.find(value, node.left_child)
else:
if node.right_child is None:
return node
else:
return self.find(value, node.right_child)

def balance(self, node):
''' There are four posabilities for rotation
left-left=LL right-right=RR
left-right=LR right-left=RL'''
node.update_height(False)
if node.balance == 2:
if node.left_child.balance != -1:
# LL rotation
self.rotate_right(node)
if node.parent.parent is not None:
self.balance(node.parent.parent)
else:
# LR rotation
self.rotate_left(node.left_child)
self.balance(node)
elif node.balance == -2:
if node.right_child.balance != 1:
# RR rotation
self.rotate_left(node)
if node.parent.parent is not None:
self.balance(node.parent.parent)

else:
# RL rotation
self.rotate_right(node.right_child)
self.balance(node)
else:
if node.parent is not None:
self.balance(node.parent)

def sort(self, tree_maker, ascending=True):
b = BST()
for item in tree_maker:
b.insert(item)
ret_value = []
if ascending:
node = b.find_leftmost(b.root)
if node is not None:
value = node.value
else:
value = node
while (value is not None):
ret_value.append(value)
value = b.find_next(value)

else:
node = b.find_rightmost(b.root)
if node is not None:
value = node.value
else:
value = node
while (value is not None):
ret_value.append(value)
value = b.find_prev(value)
return ret_value


if __name__ == '__main__':

Expand Down
29 changes: 29 additions & 0 deletions hash_table.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
class HashTable(object):
"""Implment hash table"""

def __init__(self, size=1024):
self._list_size = size
self._hash_list = [[] for _hash in xrange(0, size)]

def hash(self, key):
if not isinstance(key, basestring):
raise TypeError("Key must be in string format")
ord_val = 0
for letter in key:
ord_val += ord(letter)
return ord_val % self._list_size

def set(self, key, value):
hash = self.hash(key)
for item in self._hash_list[hash]:
if item[0] == key:
item[1] = value
return
self._hash_list[hash].append([key, value])

def get(self, key):
hash = self.hash(key)
for item in self._hash_list[hash]:
if item[0] == key:
return item[1]
raise KeyError("Key not found")
28 changes: 24 additions & 4 deletions test_bst.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,11 @@ def test_big_size():
assert t.size() == 1000


def test_balance():
def test_is_balanced():
t = BST()
for i in range(10):
t.insert(i)
assert t.balance() == -9
assert t.is_balanced() == -9


def test_negative_input():
Expand All @@ -66,11 +66,11 @@ def test_negative_input():
assert t.contains(i) is True


def test_negative_input_balance():
def test_negative_input_is_balanced():
t = BST()
for i in range(10, -10, -1):
t.insert(i)
assert t.balance() == 19
assert t.is_balanced() == 19


def test_depth():
Expand Down Expand Up @@ -167,3 +167,23 @@ def test_big_insert_delete():
bst.insert(i)
bst.delete('50')
assert bst.contains('50') is False


def test_finding_nodes():
t = [1, 4, 2, 5, 1, 3, 7, 11, 4.5]
a = BST()
for item in t:
print "inserting", item
a.insert(item)
print "End of inserts"
print "Deleting 5"
a.delete(5)
print "Deleting 1"
a.delete(True)
assert a.root.value == 4
assert a.find_next(3) == 4
assert a.find_prev(7) == 4.5
assert a.find_prev(1) is None
assert a.find_prev(7) == 4.5
assert a.find_prev(2) is None
assert a.find_prev(11) == 7
34 changes: 34 additions & 0 deletions test_hash.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
from hash_table import HashTable
import pytest


@pytest.fixture(scope='function')
def _small():
h = HashTable()
h.set('batman', 'batman')
h.set('robin', 'robin')
return h


def test_one(_small):
x = _small
assert x.get('batman') == 'batman'
assert x.get('batman') != 'robin'


def test_dict():
x = HashTable()
with open("/usr/share/dict/words", "r") as afile:
for word in afile:
word.strip()
if not word:
break
x.set(word, word)
assert x.get(word) == word


def test_ordval():
x = HashTable()
x.set('this is a really big sentence to break it',
'this is a really big sentence to break it')
assert x.get('this is a really big sentence to break it') == 'this is a really big sentence to break it'