Implemented Suffix Tree Data Structure (#11554)
* Implemented KD-Tree Data Structure
* Implemented KD-Tree Data Structure. updated DIRECTORY.md.
* [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
* Create __init__.py
* [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
* Replaced legacy `np.random.rand` call with `np.random.Generator` in kd_tree/example_usage.py
* Replaced legacy `np.random.rand` call with `np.random.Generator` in kd_tree/hypercube_points.py
* added typehints and docstrings
* [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
* docstring for search()
* [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
* Added tests. Updated docstrings/typehints
* [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
* updated tests and used | for type annotations
* [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
* E501 for build_kdtree.py, hypercube_points.py, nearest_neighbour_search.py
* I001 for example_usage.py and test_kdtree.py
* I001 for example_usage.py and test_kdtree.py
* Update data_structures/kd_tree/build_kdtree.py
Co-authored-by: Christian Clauss <cclauss@me.com>
* Update data_structures/kd_tree/example/hypercube_points.py
Co-authored-by: Christian Clauss <cclauss@me.com>
* Update data_structures/kd_tree/example/hypercube_points.py
Co-authored-by: Christian Clauss <cclauss@me.com>
* Added new test cases requested in Review. Refactored the test_build_kdtree() to include various checks.
* [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
* Considered ruff errors
* Considered ruff errors
* Apply suggestions from code review
* [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
* Update kd_node.py
* imported annotations from __future__
* [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
* Implementation of the suffix tree data structure
* Adding data to DIRECTORY.md
* Minor file renaming
* minor correction
* renaming in DIRECTORY.md
* [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
* Considering ruff part-1
* [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
* Considering ruff part-2
* [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
* Considering ruff part-3
* [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
* Considering ruff part-4
* [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
* Considering ruff part-5
* Implemented Suffix Tree Data Structure.
Added some comments to my files in #11532, #11554.
* updating DIRECTORY.md
* Implemented Suffix Tree Data Structure.
Added some comments to my files in #11532, #11554.
---------
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Christian Clauss <cclauss@me.com>
Co-authored-by: Ramy-Badr-Ahmed <Ramy-Badr-Ahmed@users.noreply.github.com>
2024-09-28 13:37:00 +00:00
|
|
|
# Created by: Ramy-Badr-Ahmed (https://github.com/Ramy-Badr-Ahmed)
|
|
|
|
# in Pull Request: #11532
|
|
|
|
# https://github.com/TheAlgorithms/Python/pull/11532
|
|
|
|
#
|
|
|
|
# Please mention me (@Ramy-Badr-Ahmed) in any issue or pull request
|
|
|
|
# addressing bugs/corrections to this file.
|
|
|
|
# Thank you!
|
|
|
|
|
kd tree data structure implementation (#11532)
* Implemented KD-Tree Data Structure
* Implemented KD-Tree Data Structure. updated DIRECTORY.md.
* [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
* Create __init__.py
* [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
* Replaced legacy `np.random.rand` call with `np.random.Generator` in kd_tree/example_usage.py
* Replaced legacy `np.random.rand` call with `np.random.Generator` in kd_tree/hypercube_points.py
* added typehints and docstrings
* [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
* docstring for search()
* [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
* Added tests. Updated docstrings/typehints
* [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
* updated tests and used | for type annotations
* [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
* E501 for build_kdtree.py, hypercube_points.py, nearest_neighbour_search.py
* I001 for example_usage.py and test_kdtree.py
* I001 for example_usage.py and test_kdtree.py
* Update data_structures/kd_tree/build_kdtree.py
Co-authored-by: Christian Clauss <cclauss@me.com>
* Update data_structures/kd_tree/example/hypercube_points.py
Co-authored-by: Christian Clauss <cclauss@me.com>
* Update data_structures/kd_tree/example/hypercube_points.py
Co-authored-by: Christian Clauss <cclauss@me.com>
* Added new test cases requested in Review. Refactored the test_build_kdtree() to include various checks.
* [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
* Considered ruff errors
* Considered ruff errors
* Apply suggestions from code review
* [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
* Update kd_node.py
* imported annotations from __future__
* [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
---------
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Christian Clauss <cclauss@me.com>
2024-09-03 12:39:09 +00:00
|
|
|
from data_structures.kd_tree.kd_node import KDNode
|
|
|
|
|
|
|
|
|
|
|
|
def nearest_neighbour_search(
|
|
|
|
root: KDNode | None, query_point: list[float]
|
|
|
|
) -> tuple[list[float] | None, float, int]:
|
|
|
|
"""
|
|
|
|
Performs a nearest neighbor search in a KD-Tree for a given query point.
|
|
|
|
|
|
|
|
Args:
|
|
|
|
root (KDNode | None): The root node of the KD-Tree.
|
|
|
|
query_point (list[float]): The point for which the nearest neighbor
|
|
|
|
is being searched.
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
tuple[list[float] | None, float, int]:
|
|
|
|
- The nearest point found in the KD-Tree to the query point,
|
|
|
|
or None if no point is found.
|
|
|
|
- The squared distance to the nearest point.
|
|
|
|
- The number of nodes visited during the search.
|
|
|
|
"""
|
|
|
|
nearest_point: list[float] | None = None
|
|
|
|
nearest_dist: float = float("inf")
|
|
|
|
nodes_visited: int = 0
|
|
|
|
|
|
|
|
def search(node: KDNode | None, depth: int = 0) -> None:
|
|
|
|
"""
|
|
|
|
Recursively searches for the nearest neighbor in the KD-Tree.
|
|
|
|
|
|
|
|
Args:
|
|
|
|
node: The current node in the KD-Tree.
|
|
|
|
depth: The current depth in the KD-Tree.
|
|
|
|
"""
|
|
|
|
nonlocal nearest_point, nearest_dist, nodes_visited
|
|
|
|
if node is None:
|
|
|
|
return
|
|
|
|
|
|
|
|
nodes_visited += 1
|
|
|
|
|
|
|
|
# Calculate the current distance (squared distance)
|
|
|
|
current_point = node.point
|
|
|
|
current_dist = sum(
|
|
|
|
(query_coord - point_coord) ** 2
|
|
|
|
for query_coord, point_coord in zip(query_point, current_point)
|
|
|
|
)
|
|
|
|
|
|
|
|
# Update nearest point if the current node is closer
|
|
|
|
if nearest_point is None or current_dist < nearest_dist:
|
|
|
|
nearest_point = current_point
|
|
|
|
nearest_dist = current_dist
|
|
|
|
|
|
|
|
# Determine which subtree to search first (based on axis and query point)
|
|
|
|
k = len(query_point) # Dimensionality of points
|
|
|
|
axis = depth % k
|
|
|
|
|
|
|
|
if query_point[axis] <= current_point[axis]:
|
|
|
|
nearer_subtree = node.left
|
|
|
|
further_subtree = node.right
|
|
|
|
else:
|
|
|
|
nearer_subtree = node.right
|
|
|
|
further_subtree = node.left
|
|
|
|
|
|
|
|
# Search the nearer subtree first
|
|
|
|
search(nearer_subtree, depth + 1)
|
|
|
|
|
|
|
|
# If the further subtree has a closer point
|
|
|
|
if (query_point[axis] - current_point[axis]) ** 2 < nearest_dist:
|
|
|
|
search(further_subtree, depth + 1)
|
|
|
|
|
|
|
|
search(root, 0)
|
|
|
|
return nearest_point, nearest_dist, nodes_visited
|