Skip to content

Commit

Permalink
Add functionality and tests for the search function
Browse files Browse the repository at this point in the history
  • Loading branch information
javiermtzo99 committed Jan 18, 2025
1 parent 69ee212 commit 9e53a6c
Show file tree
Hide file tree
Showing 4 changed files with 169 additions and 11 deletions.
44 changes: 33 additions & 11 deletions src/datastructpy/non_linear/trees/binary_search_tree.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
from datastructpy.node import Node
from datastructpy.non_linear.trees.breadth_first_search import breadth_first_search
from datastructpy.non_linear.trees.depth_first_search import depth_first_search

class BinarySearchTree:
"""
A class representing a binary search tree (BST).
Expand Down Expand Up @@ -51,25 +55,34 @@ def insert(self, key):
print(bst.root.right.key) # Output: 15
"""

def search(self, key):
def search(self, key, algorithm='dfs'):
"""
Checks if a value exists in the Binary Search Tree (BST).
Searches for a key in the Binary Search Tree (BST) using the specified algorithm.
This method allows searching for a key in the BST using either
depth-first search (DFS) or breadth-first search (BFS).
This method traverses the BST to determine if a node with the specified key exists.
It starts from the root and:
- Returns True if a node with the given key is found.
- Returns False if the key is not present in the tree.
- DFS (default)**: Searches by exploring as deep as possible before backtracking.
- BFS: Searches level by level, ensuring the shortest path to a node is checked first.
Parameters
----------
key : int
The value to search for in the tree.
algorithm : str, optional
The search algorithm to use ('dfs' for Depth-First Search or 'bfs' for Breadth-First Search).
Defaults to 'dfs'.
Returns
-------
bool
- True if a node with the specified key exists in the tree.
- False if the key does not exist or the tree is empty.
Node or None
- The Node object containing the specified key if found.
- None if the key does not exist or the tree is empty.
Raises
------
ValueError
If an invalid algorithm is provided.
Examples
--------
Expand All @@ -80,9 +93,18 @@ def search(self, key):
bst.insert(15)
# Searching for values in the tree
print(bst.search(5)) # Output: True (5 exists in the tree)
print(bst.search(20)) # Output: False (20 does not exist in the tree)
result = bst.search(5)
if result:
print(result.key) # Output: 5
print(bst.search(20)) # Output: None (20 does not exist in the tree)
"""
if algorithm == 'bfs':
return breadth_first_search(self.root, key)
elif algorithm == 'dfs':
return depth_first_search(self.root, key)
else:
raise ValueError(f"Invalid search algorithm: {algorithm}. Use 'dfs' or 'bfs'.")

def delete(self, key):
"""Delete a value from the BST.
Expand Down
32 changes: 32 additions & 0 deletions src/datastructpy/non_linear/trees/breadth_first_search.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
from collections import deque
from datastructpy.node import Node

def breadth_first_search(root, key):
"""
Performs a breadth-first search (BFS) on a binary search tree.
Parameters:
----------
root (Node): The root of the BST.
key (int): The value to search for.
Returns:
----------
Node or None: The node containing the key, or None if not found.
"""
if not root:
return None

queue = deque([root])

while queue:
node = queue.popleft()
if node.key == key:
return node # Found the key

if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)

return None # Key not found
28 changes: 28 additions & 0 deletions src/datastructpy/non_linear/trees/depth_first_search.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
from datastructpy.node import Node

def depth_first_search(root, key):
"""
Performs a depth-first search (DFS) on a binary search tree.
Parameters:
----------
root (Node): The root of the BST.
key (int): The value to search for.
Returns:
----------
Node or None: The node containing the key, or None if not found.
"""
if not root:
return None

if root.key == key:
return root # Found the key

# Search left subtree
left_result = depth_first_search(root.left, key)
if left_result:
return left_result

# Search right subtree
return depth_first_search(root.right, key)
76 changes: 76 additions & 0 deletions tests/non-linear/trees/binary_search_tree/test_search.py
Original file line number Diff line number Diff line change
@@ -1 +1,77 @@
import pytest
from datastructpy.non_linear.trees.binary_search_tree import BinarySearchTree

@pytest.fixture
def bst():
r"""
Fixture to create a Binary Search Tree (BST) with predefined values.
The tree structure:
10
/ \
5 15
/ \ / \
3 7 13 18
"""
elements = [10, 5, 15, 3, 7, 13, 18]
return BinarySearchTree.list_to_tree(elements)

@pytest.mark.parametrize("key, expected", [
(10, True), # Root node
(5, True), # Left child of root
(15, True), # Right child of root
(3, True), # Left child of 5
(7, True), # Right child of 5
(13, True), # Left child of 15
(18, True), # Right child of 15
(20, False), # Not in tree
(-1, False), # Not in tree
])
def test_search_dfs(bst, key, expected):
"""
Tests depth-first search (DFS) in BST.
Ensures DFS correctly identifies if a key exists in the tree.
"""
result = bst.search(key, algorithm='dfs')
assert (result is not None) == expected

@pytest.mark.parametrize("key, expected", [
(10, True), # Root node
(5, True), # Left child of root
(15, True), # Right child of root
(3, True), # Left child of 5
(7, True), # Right child of 5
(13, True), # Left child of 15
(18, True), # Right child of 15
(20, False), # Not in tree
(-1, False), # Not in tree
])
def test_search_bfs(bst, key, expected):
"""
Tests breadth-first search (BFS) in BST.
Ensures BFS correctly identifies if a key exists in the tree.
"""
result = bst.search(key, algorithm='bfs')
assert (result is not None) == expected

def test_search_default_algorithm(bst):
"""
Ensures that search() defaults to DFS when no algorithm is specified.
"""
assert bst.search(7) is not None # Should be found using DFS
assert bst.search(20) is None # Should not be found

def test_search_empty_tree():
"""
Tests searching in an empty BST.
The search should return None for any key.
"""
empty_bst = BinarySearchTree()
assert empty_bst.search(10) is None # Should return None

def test_search_invalid_algorithm(bst):
"""
Tests if search() handles invalid algorithm names properly.
"""
with pytest.raises(ValueError):
bst.search(10, algorithm='invalid_algorithm')

0 comments on commit 9e53a6c

Please sign in to comment.