diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..5ca17cf --- /dev/null +++ b/.travis.yml @@ -0,0 +1,5 @@ +language: python +python: + - "2.7" +install: "pip install -r requirements.txt" +script: py.test \ No newline at end of file diff --git a/README.md b/README.md index 66d0f71..8f20562 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,14 @@ Code Fellows Dev Accelerator: This repository will be for implementations of classic data structures in python. -parens.py: +## parens.py: Includes a function balanceness() that takes string and determines if it is 'open', 'balanced', or 'broken', depending on the sequence of parenthesis contained. 'Open', 'balanced', and 'broken' are respectively determined as more leading '('s than ')'s, equal number of leading '(' and ')', and any sequence including ')' that do not have a preceding '('. 'Open' strings are represented by returning a 1, 'balanced' by 0, and 'broken' by -1, with an emptry string being considered 'balanced'. -bst.py: +## bst.py: Binary search tree is a tree where each node has a left child and a right -child and every left child is smaller and every right child is larger. We implement it with a dictionary where each key is the value of the node and each value has three things in it, depth, left child and right child. \ No newline at end of file +child and every left child is smaller and every right child is larger. We implement it with a dictionary where each key is the value of the node and each value has three things in it, depth, left child and right child. This module includes a Bst class and the following functions: insert, balance, contains, size, depth, get\_dot. It also includes generators that traverse the tree in order: in\_order, pre\_order, post\_order, and breadth\_first. + + + +## Resources: +[Wikipedia Breadth First Search](en.wikipedia.org/wiki/Breadth-first_search) diff --git a/bst.py b/bst.py index df61139..bb6d302 100755 --- a/bst.py +++ b/bst.py @@ -1,6 +1,7 @@ #!/usr/bin/env python import random import subprocess +from collections import deque class Bst(object): @@ -17,6 +18,14 @@ def __init__(self, value=None): self._size += 1 self._depth += 1 + def left(self, current): + return self.tree[current].get('left') + + + def right(self, current): + return self.tree[current].get('right') + + def insert(self, value): """Insert a node with value in order. @@ -34,10 +43,10 @@ def insert(self, value): if current == value: return if current < value: - traverse = self.tree[current].get('right') + traverse = self.right(current) child = 'right' else: - traverse = self.tree[current].get('left') + traverse = self.left(current) child = 'left' if traverse is None: #actual insert @@ -49,7 +58,6 @@ def insert(self, value): return current = traverse - def balance(self): """Returns the balance of the tree: @@ -91,7 +99,6 @@ def get_dot(self): ) )) - def _get_dot(self, current): """recursively prepare a dot graph entry for this node.""" left = self.tree[current].get('left') @@ -113,14 +120,65 @@ def _get_dot(self, current): yield "\tnull%s [shape=point];" % r yield "\t%s -> null%s;" % (current, r) + def in_order(self, current='start'): + """ + Generator that traverses the binary tree in order. + """ + if current == 'start': + current = self.top + if current is not None: + for node in self.in_order(self.left(current)): + yield node + yield current + for node in self.in_order(self.right(current)): + yield node + + + def pre_order(self, current='dutch'): + """Generator that traverses the binary tree pre order.""" + if current == 'dutch': + current = self.top + if current is not None: + yield current + for node in self.pre_order(self.left(current)): + yield node + for node in self.pre_order(self.right(current)): + yield node + + def post_order(self, current='dutch'): + """Generator that traverses the binary tree post order.""" + if current == 'dutch': + current = self.top + if current is not None: + for node in self.post_order(self.left(current)): + yield node + for node in self.post_order(self.right(current)): + yield node + yield current + + def breadth_first(self): + """Generator that traverses the binary tree in breadth first order.""" + q1 = deque() + q1.appendleft(self.top) + current = self.top + while q1: + current = q1.pop() + if self.left(current) is not None: + q1.appendleft(self.left(current)) + if self.right(current) is not None: + q1.appendleft(self.right(current)) + yield current + def main(): """Best case and worst case are the same.""" tree = Bst() - for num in reversed(range(10)): - tree.insert(num) - for num in range(10, 15): - tree.insert(num) + inserts = [7, 4, 11, 2, 9, 6, 12, 5, 13, 0, 10, 8, 3, 1] + for i in inserts: + tree.insert(i) + print tree.tree + # for num in enumerate(tree.pre_order()): + # print num dot_graph = tree.get_dot() t = subprocess.Popen(["dot", "-Tpng"], stdin=subprocess.PIPE) t.communicate(dot_graph) diff --git a/linked_list.py b/linked_list.py index 7458b48..a6bc65c 100644 --- a/linked_list.py +++ b/linked_list.py @@ -35,6 +35,8 @@ def insert(self, val): Set .data attribute to val and rearrange the list so the head is the new node with a reference to the old head. """ + # if isinstance(val, unicode): + # val = val.encode('utf-8') self.head = List_Node(val, self.head) self._size += 1 @@ -104,7 +106,7 @@ def display_prep(self): while temp: dummy = temp.data if isinstance(temp.data, str or unicode): - dummy = "'{}'".format(dummy.encode('utf-8')) + dummy = "'{}'".format(dummy) if temp is self.head: output = "{}{}".format(output, dummy) @@ -113,5 +115,4 @@ def display_prep(self): output = "{}, {}".format(output, dummy) temp = temp.next - return output + ")" diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..625ffd1 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +py==1.4.26 +pytest==2.6.4 diff --git a/test_bst.py b/test_bst.py index 2cadfec..d1d546c 100644 --- a/test_bst.py +++ b/test_bst.py @@ -57,6 +57,7 @@ def test_depth_tree(filled_tree): t = filled_tree assert t.depth() == 10 + def test_balance(empty_tree, filled_tree): t = empty_tree assert t.balance() == 0 @@ -65,6 +66,7 @@ def test_balance(empty_tree, filled_tree): t = filled_tree assert t.balance() == -5 + def test_contains(filled_tree): t = filled_tree for num in reversed(range(10)): @@ -75,8 +77,51 @@ def test_contains(filled_tree): assert t.contains(num) is False +def test_in_order(filled_tree): + tree = filled_tree + gen = tree.in_order() + expected_order = range(0, 14) + for i in expected_order: + j = gen.next() + print str(i) + '=' + str(j) + assert i == j + with pytest.raises(StopIteration): + gen.next() + + +def test_pre_order(filled_tree): + tree = filled_tree + gen = tree.pre_order() + expected_order = [9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 10, 11, 12, 13] + for i in expected_order: + j = gen.next() + print str(i) + '=' + str(j) + assert i == j + with pytest.raises(StopIteration): + gen.next() + +def test_post_order(filled_tree): + tree = filled_tree + gen = tree.post_order() + expected_order = [0, 1, 2, 3, 4, 5, 6, 7, 8, 13, 12, 11, 10, 9] + for i in expected_order: + j = gen.next() + print str(i) + '=' + str(j) + assert i == j + with pytest.raises(StopIteration): + gen.next() + + +def test_breadth_first_order(filled_tree): + tree = filled_tree + expected_order = [9, 8, 10, 7, 11, 6, 12, 5, 13, 4, 3, 2, 1, 0] + for place, item in enumerate(tree.breadth_first()): + assert expected_order[place] == item + + @pytest.fixture(scope='function') def filled_tree(): + """Upside down V Shaped Tree""" tree = bst.Bst() for num in reversed(range(10)): tree.insert(num) @@ -85,6 +130,16 @@ def filled_tree(): return tree +@pytest.fixture(scope='function') +def filled_tree_2(): + """Tree with lots of branches""" + inserts = [7, 4, 11, 2, 9, 6, 12, 5, 13, 0, 10, 8, 3, 1] + tree = bst.Bst() + for val in inserts: + tree.insert(val) + return tree + + @pytest.fixture(scope='function') def empty_tree(): tree = bst.Bst() diff --git a/test_linked_list.py b/test_linked_list.py index e959241..7728aac 100644 --- a/test_linked_list.py +++ b/test_linked_list.py @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- # test constructor from linked_list import List_Node from linked_list import Linked_List