-
-
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
Conversation
inserted = True | ||
return inserted | ||
|
||
def search(self, searched_number): |
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.
I recommend changing searched_number to either number
or search_number
, searched is in past tense which means you've already searched for it.
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.
Ok, changed!
return inserted | ||
|
||
def search(self, searched_number): | ||
cur_node = self.root |
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.
Also add a check for if(self.root is None): return false
which does an early exit if the tree hasn't been constructed.
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.
Ok, checked!
|
||
def print_postorder(self, node): | ||
if(node is not None): | ||
self.print_preorder(node.left_node) |
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.
Post order should be
self.print_postorder(node.right_node) # Right comes first
self.print_postorder(node.left_node)
print(node.value)
Also you're calling print_preorder()
.
found = False | ||
while not found: | ||
if(cur_node is None): | ||
raise ValueError("Element not found") |
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.
You won't need to raise an exception if you do an early return false
…e tree root is none
config.json
Outdated
@@ -888,9 +888,22 @@ | |||
"uuid": "6b7f7b1f-c388-4f4c-b924-84535cc5e1a0", | |||
"slug": "hexadecimal", | |||
"deprecated": true | |||
}, |
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.
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.
Looks good overall, but there are a couple of issues that need to be resolved.
@@ -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 comment
The reason will be displayed to describe this comment to others. Learn more.
This needs the title of the exercise as a heading: # Binary Search Tree
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.
Done
|
||
class BinarySearchTree(object): | ||
def __init__(self): | ||
pass |
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.
Can you also include skeletons for the add
and search
methods here?
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.
Done
@@ -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 comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add self.value = value
here? I feel like if we assume that something exists in the tests, then we should make it clear in the solution template.
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.
Done
config.json
Outdated
@@ -1169,6 +1183,5 @@ | |||
} | |||
], | |||
"foregone": [ | |||
|
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.
Can you add this blank line back in?
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.
Done
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.
I looks like you've got some unnecessary white-space here now (see below) - can you please remove it?
/ \ | ||
2 6 | ||
/ \ / \ | ||
1 3 5 7 |
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.
There should also be some other stuff that goes here. Check another exercise and copy it over, or regenerate this README with the configlet
.
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.
Done
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 comment
The reason will be displayed to describe this comment to others. Learn more.
We use assertIs(actual, True)
and assertIs(actual, False)
rather than assertTrue(actual)
or assertFalse(actual)
(#419).
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.
Done
else: | ||
cur_node.right_node = TreeNode(value) | ||
inserted = True | ||
return inserted |
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.
Looking at this again, I just noticed that this method is returning True
/False
to indicate success/failure. Under what condition is failure expected to occur? From what I can see, this code will never return False
, and would actually just enter an infinite loop if value == cur_node.value
. I don't think that we should use booleans in this way - exceptions are a better method for handling errors in Python, but I don't think that any exceptions should be expected to occur here.
I think it would be worth adding a BinarySearchTree.list
method to this exercise that returns a sorted list of values in the tree. A collections.deque
would be most efficient for this, but I don't think that the tests should enforce its use, so the tests should probably convert the actual output to a list (eg. assertEqual(list(self.bst.list()), [1, 2, 3])
).
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 README
:
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.
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.
@N-Parsons Returning True
from an add or insert method is a common practice for container classes. I agree that it doesn't make the most sense, but that is likely why @rodrigocam did this.
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.
@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 comment
The reason will be displayed to describe this comment to others. Learn more.
Given that there's no way that False
can be returned, and there is no test for this method returning False
, I think it's unnecessary and likely to cause some confusion/frustration. I think it's fine for this example code to return True
/False
, but I don't think that it should be tested for.
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.
Done! I take out the return of the method.
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.
@rodrigocam Travis-CI build failed due to flake8 violations:
$ flake8
./exercises/binary-search-tree/binary_search_tree_test.py:15:46: E231 missing whitespace after ','
./exercises/binary-search-tree/binary_search_tree_test.py:15:48: E231 missing whitespace after ','
./exercises/binary-search-tree/binary_search_tree_test.py:15:50: E231 missing whitespace after ','
./exercises/binary-search-tree/binary_search_tree_test.py:15:52: E231 missing whitespace after ','
./exercises/binary-search-tree/binary_search_tree_test.py:24:48: E231 missing whitespace after ','
./exercises/binary-search-tree/binary_search_tree_test.py:24:52: E231 missing whitespace after ','
./exercises/binary-search-tree/binary_search_tree_test.py:24:56: E231 missing whitespace after ','
./exercises/binary-search-tree/binary_search_tree_test.py:24:60: E231 missing whitespace after ','
./exercises/binary-search-tree/binary_search_tree_test.py:32:46: E231 missing whitespace after ','
./exercises/binary-search-tree/binary_search_tree_test.py:32:50: E231 missing whitespace after ','
./exercises/binary-search-tree/binary_search_tree_test.py:32:54: E231 missing whitespace after ','
./exercises/binary-search-tree/binary_search_tree_test.py:40:46: E231 missing whitespace after ','
./exercises/binary-search-tree/binary_search_tree_test.py:40:48: E231 missing whitespace after ','
./exercises/binary-search-tree/binary_search_tree_test.py:40:52: E231 missing whitespace after ','
./exercises/binary-search-tree/binary_search_tree_test.py:48:1: W293 blank line contains whitespace
./exercises/binary-search-tree/example.py:3:1: E302 expected 2 blank lines, found 1
./exercises/binary-search-tree/example.py:82:30: W292 no newline at end of file
The command "flake8" failed and exited with 1 during .
bst.add(1) | ||
bst.add(7.5) | ||
self.assertIs(bst.search(6), False) | ||
self.assertIs(bst.search(8.8), False) |
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.
I don't like that search
will sometimes return a bool
and sometimes return a TreeNode
. I think that this should either be TreeNode
/None
, or True
/False
- the former is perhaps more generally useful, since nodes are truthy and None
is falsey, and returning the actual node could be useful in some instances.
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.
Done! I change to return None when the node is not found.
def add(self, value): | ||
pass | ||
|
||
def search(self, search_number): |
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.
I think this should use value
rather than search_number
as an argument, since we put values in and then search for them, and search_
is probably redundant.
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.
Done!
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.
@rodrigocam, it looks like you've updated this in example.py
but not here.
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.
Ok, done!
"binary_search_tree_test.py::BinarySearchTreeTests::test_search_valid_number1": true, | ||
"binary_search_tree_test.py::BinarySearchTreeTests::test_search_valid_number2": true, | ||
"binary_search_tree_test.py::BinarySearchTreeTests::test_search_valid_number3": true | ||
} |
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.
You need to remove the .cache
directory.
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.
Done!
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.
Done!
Hi @rodrigocam, sorry for taking a while to get back to this - I've had a really busy couple of weeks! There are a couple of minor issues remaining that need to be dealt with, and then this can be merged. |
config.json
Outdated
@@ -1185,6 +1199,6 @@ | |||
} | |||
], | |||
"foregone": [ | |||
|
|||
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.
@rodrigocam, the extra spaces here also need to be removed. There should be a blank line, but there should be nothing in it.
@cmccandless, can you review this again? There are a couple of minor changes pending and then I think this will be ready to merge. |
elements.append(node.value) | ||
self.trav_inorder(node.right_node, elements) | ||
|
||
def print_inorder(self, node): |
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.
We should probably remove all print*
methods, as they are not used by the tests.
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.
Done!
Looks good. Thanks @rodrigocam! |
Resolved #740