-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement exercise binary-search-tree #773
Changes from 12 commits
cae11fe
d8256db
5b65169
06b303f
b39e8d8
a5350dc
5604b08
1013ec8
5883681
ab2fa3e
1425ffc
cb4e3bf
fed194a
9990ec2
7192861
3fe384e
62c5933
49f6701
10627f2
f4d558f
5663d14
56f971b
fa1de56
805557a
3b916a5
1332fdc
cd94b1f
18c399f
a01cb5a
c054b29
d43a2ba
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1112,6 +1112,20 @@ | |
"exception_handling" | ||
] | ||
}, | ||
{ | ||
"uuid": "6f196341-0ffc-9780-a7ca-1f817508247161cbcd9", | ||
"slug": "binary-search-tree", | ||
"core": false, | ||
"unlocked_by": null, | ||
"difficulty": 4, | ||
"topics":[ | ||
"recursion", | ||
"classes", | ||
"trees", | ||
"searching", | ||
"object_oriented_programming" | ||
] | ||
}, | ||
{ | ||
"uuid": "e7351e8e-d3ff-4621-b818-cd55cf05bffd", | ||
"slug": "accumulate", | ||
|
@@ -1166,9 +1180,8 @@ | |
"uuid": "6b7f7b1f-c388-4f4c-b924-84535cc5e1a0", | ||
"slug": "hexadecimal", | ||
"deprecated": true | ||
} | ||
}, | ||
], | ||
"foregone": [ | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you add this blank line back in? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I looks like you've got some unnecessary white-space here now (see below) - can you please remove it? |
||
] | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
Insert and search for numbers in a binary tree. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This needs the title of the exercise as a heading: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||
|
||
When we need to represent sorted data, an array does not make a good | ||
data structure. | ||
|
||
Say we have the array `[1, 3, 4, 5]`, and we add 2 to it so it becomes | ||
`[1, 3, 4, 5, 2]` now we must sort the entire array again! We can | ||
improve on this by realizing that we only need to make space for the new | ||
item `[1, nil, 3, 4, 5]`, and then adding the item in the space we | ||
added. But this still requires us to shift many elements down by one. | ||
|
||
Binary Search Trees, however, can operate on sorted data much more | ||
efficiently. | ||
|
||
A binary search tree consists of a series of connected nodes. Each node | ||
contains a piece of data (e.g. the number 3), a variable named `left`, | ||
and a variable named `right`. The `left` and `right` variables point at | ||
`nil`, or other nodes. Since these other nodes in turn have other nodes | ||
beneath them, we say that the left and right variables are pointing at | ||
subtrees. All data in the left subtree is less than or equal to the | ||
current node's data, and all data in the right subtree is greater than | ||
the current node's data. | ||
|
||
For example, if we had a node containing the data 4, and we added the | ||
data 2, our tree would look like this: | ||
|
||
4 | ||
/ | ||
2 | ||
|
||
If we then added 6, it would look like this: | ||
|
||
4 | ||
/ \ | ||
2 6 | ||
|
||
If we then added 3, it would look like this | ||
|
||
4 | ||
/ \ | ||
2 6 | ||
\ | ||
3 | ||
|
||
And if we then added 1, 5, and 7, it would look like this | ||
|
||
4 | ||
/ \ | ||
/ \ | ||
2 6 | ||
/ \ / \ | ||
1 3 5 7 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There should also be some other stuff that goes here. Check another exercise and copy it over, or regenerate this README with the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
class TreeNode(object): | ||
def __init__(self, value): | ||
pass | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you add There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||
|
||
|
||
class BinarySearchTree(object): | ||
def __init__(self): | ||
pass | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you also include skeletons for the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import unittest | ||
|
||
from binary_search_tree import BinarySearchTree | ||
|
||
|
||
class BinarySearchTreeTests(unittest.TestCase): | ||
bst = BinarySearchTree() | ||
|
||
def test_add_integer_number1(self): | ||
self.assertTrue(self.bst.add(7)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||
|
||
def test_add_integer_number2(self): | ||
self.assertTrue(self.bst.add(1)) | ||
|
||
def test_add_integer_number3(self): | ||
self.assertTrue(self.bst.add(6)) | ||
|
||
def test_add_integer_number4(self): | ||
self.assertTrue(self.bst.add(5)) | ||
|
||
def test_add_float_number(self): | ||
self.assertTrue(self.bst.add(7.5)) | ||
|
||
def test_search_valid_number1(self): | ||
self.assertEqual(self.bst.search(7).value, 7) | ||
|
||
def test_search_valid_number2(self): | ||
self.assertEqual(self.bst.search(7.5).value, 7.5) | ||
|
||
def test_search_valid_number3(self): | ||
self.assertEqual(self.bst.search(1).value, 1) | ||
|
||
|
||
if __name__ == '__main__': | ||
unittest.main() |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
class TreeNode(object): | ||
def __init__(self, value): | ||
self.value = value | ||
self.left_node = None | ||
self.right_node = None | ||
|
||
def __str__(self): | ||
return str(self.value) | ||
|
||
|
||
class BinarySearchTree(object): | ||
def __init__(self): | ||
self.root = None | ||
|
||
def add(self, value): | ||
if(self.root is None): | ||
self.root = TreeNode(value) | ||
inserted = True | ||
return inserted | ||
else: | ||
inserted = False | ||
cur_node = self.root | ||
|
||
while not inserted: | ||
if(value < cur_node.value): | ||
if(cur_node.left_node): | ||
cur_node = cur_node.left_node | ||
else: | ||
cur_node.left_node = TreeNode(value) | ||
inserted = True | ||
return inserted | ||
elif(value > cur_node.value): | ||
if(cur_node.right_node): | ||
cur_node = cur_node.right_node | ||
else: | ||
cur_node.right_node = TreeNode(value) | ||
inserted = True | ||
return inserted | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looking at this again, I just noticed that this method is returning I think it would be worth adding a Doing this would allow us to check that values are placed in the right order - each test for adding a number should contain a second assert for the current list of stored values. We should also test duplicate values, because the README specifies a way for these to be handled. From the
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @N-Parsons Returning There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @cmccandless is right, I thought this could be good to give more safety. I made the list method that @N-Parsons asked and change the tests to use this new method. I fix the infinite loop condition that you point but I keep the bool return, if it was a problem I can remove (: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Given that there's no way that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done! I take out the return of the method. |
||
|
||
def search(self, search_number): | ||
cur_node = self.root | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also add a check for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok, checked! |
||
found = False | ||
while not found: | ||
if(cur_node is None): | ||
return False | ||
elif(search_number < cur_node.value): | ||
cur_node = cur_node.left_node | ||
elif(search_number > cur_node.value): | ||
cur_node = cur_node.right_node | ||
elif(search_number == cur_node.value): | ||
return cur_node | ||
|
||
def print_inorder(self, node): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should probably remove all There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done! |
||
if(node is not None): | ||
self.print_inorder(node.left_node) | ||
print(node.value) | ||
self.print_inorder(node.right_node) | ||
|
||
def print_preorder(self, node): | ||
if(node is not None): | ||
print(node.value) | ||
self.print_preorder(node.left_node) | ||
self.print_preorder(node.right_node) | ||
|
||
def print_postorder(self, node): | ||
if(node is not None): | ||
self.print_postorder(node.right_node) | ||
self.print_postorder(node.left_node) | ||
print(node.value) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would probably be best to move the
config.json
entry for this exercise before all deprecated exercises.