Skip to content

Commit 7b89950

Browse files
Copilotdjeada
andauthored
Modernize Python sorting algorithm implementations (#28)
* Initial plan * fix: modernize Python sorting algorithm implementations and tests Co-authored-by: djeada <37275728+djeada@users.noreply.github.com> * fix: modernize C++ sorting algorithm implementations and tests Co-authored-by: djeada <37275728+djeada@users.noreply.github.com> * fix: address code review feedback for C++ documentation Co-authored-by: djeada <37275728+djeada@users.noreply.github.com> * feat: implement searching algorithms in Python and C++ Co-authored-by: djeada <37275728+djeada@users.noreply.github.com> * fix: correct typos in CMake files Co-authored-by: djeada <37275728+djeada@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: djeada <37275728+djeada@users.noreply.github.com>
1 parent a9e90c7 commit 7b89950

95 files changed

Lines changed: 2619 additions & 389 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
cmake_minimum_required(VERSION 3.15 FATAL_ERROR)
2+
3+
project(project-binary-search CXX)
4+
5+
include(GNUInstallDirs)
6+
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR})
7+
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR})
8+
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR})
9+
10+
if(CMAKE_CXX_COMPILER_ID MATCHES GNU)
11+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage")
12+
endif()
13+
14+
add_subdirectory(src)
15+
16+
include(cmake/googletest.cmake)
17+
fetch_googletest(${PROJECT_SOURCE_DIR}/cmake ${PROJECT_BINARY_DIR}/googletest)
18+
19+
enable_testing()
20+
add_subdirectory(test)
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# code copied from https://crascit.com/2015/07/25/cmake-gtest/
2+
cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
3+
4+
project(googletest-download NONE)
5+
6+
include(ExternalProject)
7+
8+
ExternalProject_Add(
9+
googletest
10+
SOURCE_DIR "@GOOGLETEST_DOWNLOAD_ROOT@/googletest-src"
11+
BINARY_DIR "@GOOGLETEST_DOWNLOAD_ROOT@/googletest-build"
12+
GIT_REPOSITORY
13+
https://github.com/google/googletest.git
14+
GIT_TAG
15+
release-1.8.0
16+
CONFIGURE_COMMAND ""
17+
BUILD_COMMAND ""
18+
INSTALL_COMMAND ""
19+
TEST_COMMAND ""
20+
)
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# the following code to fetch googletest
2+
# is inspired by and adapted after https://crascit.com/2015/07/25/cmake-gtest/
3+
# download and unpack googletest at configure time
4+
5+
macro(fetch_googletest _download_module_path _download_root)
6+
set(GOOGLETEST_DOWNLOAD_ROOT ${_download_root})
7+
configure_file(
8+
${_download_module_path}/googletest-download.cmake
9+
${_download_root}/CMakeLists.txt
10+
@ONLY
11+
)
12+
unset(GOOGLETEST_DOWNLOAD_ROOT)
13+
14+
execute_process(
15+
COMMAND
16+
"${CMAKE_COMMAND}" -G "${CMAKE_GENERATOR}" .
17+
WORKING_DIRECTORY
18+
${_download_root}
19+
)
20+
execute_process(
21+
COMMAND
22+
"${CMAKE_COMMAND}" --build .
23+
WORKING_DIRECTORY
24+
${_download_root}
25+
)
26+
27+
# adds the targets: gtest, gtest_main, gmock, gmock_main
28+
add_subdirectory(
29+
${_download_root}/googletest-src
30+
${_download_root}/googletest-build
31+
)
32+
endmacro()
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
add_library(binary_search "")
2+
3+
target_sources(
4+
binary_search
5+
PRIVATE binary_search.cpp
6+
PUBLIC ${CMAKE_CURRENT_LIST_DIR}/binary_search.h)
7+
8+
target_include_directories(binary_search PUBLIC ${CMAKE_CURRENT_LIST_DIR})
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#include "binary_search.h"
2+
3+
#include <cstddef>
4+
#include <optional>
5+
#include <vector>
6+
7+
template <typename T>
8+
std::optional<std::size_t> binary_search(const std::vector<T> &arr, const T &target) {
9+
if (arr.empty()) {
10+
return std::nullopt;
11+
}
12+
13+
std::size_t low = 0;
14+
std::size_t high = arr.size() - 1;
15+
16+
while (low <= high) {
17+
std::size_t mid = low + (high - low) / 2;
18+
if (arr[mid] == target) {
19+
return mid;
20+
} else if (arr[mid] < target) {
21+
low = mid + 1;
22+
} else {
23+
if (mid == 0) {
24+
break;
25+
}
26+
high = mid - 1;
27+
}
28+
}
29+
30+
return std::nullopt;
31+
}
32+
33+
// Explicit template instantiations
34+
template std::optional<std::size_t> binary_search<int>(const std::vector<int> &arr, const int &target);
35+
template std::optional<std::size_t> binary_search<float>(const std::vector<float> &arr, const float &target);
36+
template std::optional<std::size_t> binary_search<double>(const std::vector<double> &arr, const double &target);
37+
template std::optional<std::size_t> binary_search<char>(const std::vector<char> &arr, const char &target);
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#ifndef BINARY_SEARCH_H
2+
#define BINARY_SEARCH_H
3+
4+
#include <optional>
5+
#include <vector>
6+
7+
/**
8+
* @brief Search for a target value in a sorted array using binary search.
9+
*
10+
* This algorithm repeatedly halves the search interval by comparing the
11+
* target to the middle element until found or the interval is empty.
12+
*
13+
* @tparam T The type of elements in the vector (must be comparable).
14+
* @param arr The sorted vector of elements to search.
15+
* @param target The value to search for.
16+
* @return The index of the target if found, std::nullopt otherwise.
17+
*
18+
* @note Time complexity: O(log n)
19+
* @note Space complexity: O(1)
20+
* @note The array must be sorted in ascending order.
21+
*/
22+
template <typename T>
23+
std::optional<std::size_t> binary_search(const std::vector<T> &arr, const T &target);
24+
25+
#endif // BINARY_SEARCH_H
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
add_executable(unit_tests test_binary_search.cpp)
2+
3+
target_link_libraries(unit_tests gtest_main binary_search)
4+
5+
add_test(NAME unit
6+
COMMAND ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}/unit_tests)
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
int main(int argc, char **argv) {
2+
::testing::InitGoogleTest(&argc, argv);
3+
return RUN_ALL_TESTS();
4+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/**
2+
* @file test_binary_search.cpp
3+
* @brief Unit tests for the binary search algorithm.
4+
*/
5+
6+
#include "binary_search.h"
7+
#include "gtest/gtest.h"
8+
9+
/// @brief Test searching an empty array.
10+
TEST(BinarySearchTest, EmptyArray) {
11+
std::vector<int> arr;
12+
EXPECT_EQ(binary_search(arr, 5), std::nullopt);
13+
}
14+
15+
/// @brief Test finding the only element in a single-element array.
16+
TEST(BinarySearchTest, SingleElementFound) {
17+
std::vector<int> arr{5};
18+
EXPECT_EQ(binary_search(arr, 5), 0);
19+
}
20+
21+
/// @brief Test not finding element in a single-element array.
22+
TEST(BinarySearchTest, SingleElementNotFound) {
23+
std::vector<int> arr{5};
24+
EXPECT_EQ(binary_search(arr, 3), std::nullopt);
25+
}
26+
27+
/// @brief Test target at the first position.
28+
TEST(BinarySearchTest, TargetAtBeginning) {
29+
std::vector<int> arr{1, 2, 3, 4, 5};
30+
EXPECT_EQ(binary_search(arr, 1), 0);
31+
}
32+
33+
/// @brief Test target at the last position.
34+
TEST(BinarySearchTest, TargetAtEnd) {
35+
std::vector<int> arr{1, 2, 3, 4, 5};
36+
EXPECT_EQ(binary_search(arr, 5), 4);
37+
}
38+
39+
/// @brief Test target in the middle of the array.
40+
TEST(BinarySearchTest, TargetInMiddle) {
41+
std::vector<int> arr{1, 2, 3, 4, 5};
42+
EXPECT_EQ(binary_search(arr, 3), 2);
43+
}
44+
45+
/// @brief Test target smaller than all elements.
46+
TEST(BinarySearchTest, TargetTooSmall) {
47+
std::vector<int> arr{2, 4, 6, 8, 10};
48+
EXPECT_EQ(binary_search(arr, 1), std::nullopt);
49+
}
50+
51+
/// @brief Test target larger than all elements.
52+
TEST(BinarySearchTest, TargetTooLarge) {
53+
std::vector<int> arr{2, 4, 6, 8, 10};
54+
EXPECT_EQ(binary_search(arr, 12), std::nullopt);
55+
}
56+
57+
/// @brief Test target in gap between elements.
58+
TEST(BinarySearchTest, TargetInGap) {
59+
std::vector<int> arr{2, 4, 6, 8, 10};
60+
EXPECT_EQ(binary_search(arr, 5), std::nullopt);
61+
}
62+
63+
/// @brief Test searching with negative numbers.
64+
TEST(BinarySearchTest, WithNegativeNumbers) {
65+
std::vector<int> arr{-10, -5, 0, 5, 10};
66+
EXPECT_EQ(binary_search(arr, -5), 1);
67+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
cmake_minimum_required(VERSION 3.15 FATAL_ERROR)
2+
3+
project(project-exponential-search CXX)
4+
5+
include(GNUInstallDirs)
6+
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR})
7+
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR})
8+
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR})
9+
10+
if(CMAKE_CXX_COMPILER_ID MATCHES GNU)
11+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage")
12+
endif()
13+
14+
add_subdirectory(src)
15+
16+
include(cmake/googletest.cmake)
17+
fetch_googletest(${PROJECT_SOURCE_DIR}/cmake ${PROJECT_BINARY_DIR}/googletest)
18+
19+
enable_testing()
20+
add_subdirectory(test)

0 commit comments

Comments
 (0)