Skip to content

Commit

Permalink
Added chapters 04,05,06 and latest exercises (#7)
Browse files Browse the repository at this point in the history
  • Loading branch information
thorstendikmann committed Jun 23, 2024
1 parent 2d9c436 commit be73f8c
Show file tree
Hide file tree
Showing 43 changed files with 1,573 additions and 0 deletions.
4 changes: 4 additions & 0 deletions src/chapter/04_search/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin/c04)
include_directories(${CMAKE_CURRENT_SOURCE_DIR})

td_add_all_subdirectories()
13 changes: 13 additions & 0 deletions src/chapter/04_search/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Search

Contains implementations for search algorithms.

## Fields / Arrays / Queues / Stacks

- [searcharray](searcharray)
C++ implementation of several search algorithms in a Template.

<!--
- [array](array)
Utilizes the [array](../02_datastructures/array) to illustrate certain search algorithms implemented in C.
-->
7 changes: 7 additions & 0 deletions src/chapter/04_search/searcharray/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
add_library(searcharray searcharray.cpp searcharray.h)
set_target_properties(searcharray PROPERTIES PUBLIC_HEADER "searcharray.h")
install(TARGETS searcharray PUBLIC_HEADER DESTINATION include/searcharray)

add_executable(searcharray_test searcharray_test.cpp)
target_link_libraries(searcharray_test searcharray)
install(TARGETS searcharray_test DESTINATION bin/c04)
6 changes: 6 additions & 0 deletions src/chapter/04_search/searcharray/searcharray.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/**
* When working with templates, the function definition (body)
* must be implemented in the header file.
* Implementation here works with GCC, but not with CLang.
*/
#include "searcharray.h"
220 changes: 220 additions & 0 deletions src/chapter/04_search/searcharray/searcharray.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,220 @@
#ifndef SEARCHARRAY_H
#define SEARCHARRAY_H

#include <iostream>

#include "dynarray/dynarray.h"

namespace fom
{
namespace AuD
{
/**
* Templated Array implementation in C++ for illustrating search functions.
*/
template <typename T>
class SearchArray : public Array<T>
{

public:
/** Default constructor. */
SearchArray();
/** Destructor, free's resources. */
virtual ~SearchArray();

/**
* "Sequential" search, searching the Array "from left to right".
* @return position of the found element. -1 if not found.
*/
int search_sequential(const T &val) const;

/**
* "Binary" search algorithms.
* Internally calls search_binary_rec() recursively.
* @return position of the found element. -1 if not found.
*/
int search_binary(const T &val) const;

/**
* Interpolation search.
* Internally calls search_interpolation_rec() recursively
* @return position of the found element. -1 if not found.
*/
int search_interpolation(const T &val) const;

/**
* Exponential search.
* @return position of the found element. -1 if not found.
*/
int search_exponential(const T &val) const;

protected:
/**
* Recursive implementation of the binary search algorithms.
* @param steps just a counter for keeping track of the steps.
* @param val the value to be searched for.
* @param left the "lower" limit in the binary search algorithm.
* @param right the "upper" limit in the binary search algorithm.
*/
int search_binary_rec(std::size_t& steps, const T &val, std::size_t left, std::size_t right) const;

/**
* Recursive implementation of the interpolation search algorithms.
*
* \f[
* i = l + \frac{r-l}{a[r]-a[l]}\cdot\left( x-a[l] \right)
* \f]
* where \f$ x \f$ the value we're looking for, \f$ i \f$ is the next "probing" position,
* \f$ a \f$ this array, \f$ l \f$ the left boundary and \f$ r \f$ the right boundary.
* @param steps just a counter for keeping track of the steps.
* @param val the value to be searched for.
* @param left the "lower" limit in the search algorithm.
* @param right the "upper" limit in the search algorithm.
*/
int search_interpolation_rec(std::size_t& steps, const T &val, std::size_t left, std::size_t right) const;
};
}
}

/**
* Output function for fom::AuD::SearchArray<T>.
* Needs to be defined in header, see https://stackoverflow.com/questions/8752837/undefined-reference-to-template-class-constructor .
*/
template <typename T>
std::ostream &operator<<(std::ostream &os, const fom::AuD::SearchArray<T> &o)
{
os << o.toString();
return os;
}

namespace fom
{
namespace AuD
{

template <typename T>
SearchArray<T>::SearchArray() : Array<T>()
{
}

template <typename T>
SearchArray<T>::~SearchArray()
{
// superclass destructor called automatically!
}

template <typename T>
int SearchArray<T>::search_sequential(const T &val) const
{
std::size_t idx = 0;
for (typename Array<T>::const_iterator cItr = this->begin(); cItr != this->end(); ++cItr)
{
this->callback({idx});
if (*cItr == val)
{
return idx;
}
++idx;
}

return -1;
}

template <typename T>
int SearchArray<T>::search_binary(const T &val) const
{
this->callback({0, this->size() - 1});
std::size_t steps = 0;
int returnVal = search_binary_rec(steps, val, 0, this->size() - 1);

return returnVal;
}

template <typename T>
int SearchArray<T>::search_binary_rec(std::size_t& steps, const T &val, std::size_t left, std::size_t right) const
{
steps++;
if (right >= left)
{
std::cout << " Step " << steps << std::endl;
std::size_t mid = left + (right - left) / 2;
this->callback({mid, left, right});

// element is at the middle
if (this->at(mid) == val)
return mid;

// element < mid, then consider "left" subarray [with mid-1 as right border]
if (this->at(mid) > val)
return search_binary_rec(steps, val, left, mid - 1);

// element > mid, then consider "right" subarray [with mid+1 as left border]
return search_binary_rec(steps, val, mid + 1, right);
}

return -1;
}

template <typename T>
int SearchArray<T>::search_interpolation(const T &val) const
{
this->callback({0, this->size() - 1});
std::size_t steps = 0;
return search_interpolation_rec(steps, val, 0, this->size() - 1);
}

template <typename T>
int SearchArray<T>::search_interpolation_rec(std::size_t& steps, const T &val, std::size_t left, std::size_t right) const
{
std::size_t pos;
steps++;

// Value must be found in boundaries > left && < right
if (left <= right && (val >= this->at(left) && val <= this->at(right)))
{
std::cout << " Step " << steps << std::endl;

// Probing - see formula in function description
pos = left + (((double)(right - left) / (this->at(right) - this->at(left))) * (val - this->at(left)));
this->callback({pos, left, right});

// Found?
if (this->at(pos) == val)
return pos;

// val is larger => val in right sub array
if (this->at(pos) < val)
return search_interpolation_rec(steps, val, pos + 1, right);

// val is smaller => val in left sub array
if (this->at(pos) > val)
return search_interpolation_rec(steps, val, left, pos - 1);
}
return -1;
}

template <typename T>
int SearchArray<T>::search_exponential(const T &val) const
{
size_t n = this->size();
// found at first position?
if (this->at(0) == val)
return 0;

// Determine range of binary search
// Repeat doubling interval and check if searched value in it.
std::size_t i = 1;
while (i < n && this->at(i) <= val)
{
i = i * 2;
this->callback({i, i / 2});
}

// binary search for the found range.
std::size_t steps;
return this->search_binary_rec(steps, val, i / 2, std::min(i, n - 1));
}
}
}

#endif // SEARCHARRAY_H
75 changes: 75 additions & 0 deletions src/chapter/04_search/searcharray/searcharray_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#include <iostream>
#include <string>

#include "searcharray.h"

int main()
{
typedef fom::AuD::SearchArray<int> SearchArray;

std::cout << "#---- Some search tests on SearchArray" << std::endl;
{
SearchArray array;

array.push_back(10);
array.push_back(15);
array.push_back(1);
array.push_back(3);
array.push_back(5);
array.push_back(7);
array.push_back(9);
array.push_back(25);
array.push_back(13);
array.push_back(9);
array.push_back(45);
array.push_back(46);
array.push_back(33);
array.push_back(42);

std::cout << array.toString() << std::endl;

std::cout << "Random access of some elements: " << std::endl;
std::cout << " [0] - " << array[0] << std::endl;
std::cout << " [3] - " << array[2] << std::endl;

std::cout << "Test some other functions: " << std::endl;
std::cout << " Size: " << array.size() << std::endl;

std::cout << "#---- Sorting array (no particular algorithm)." << std::endl;
array.sort_simple();
std::cout << array.toString() << std::endl;

std::cout << "#---- Searching Sequential." << std::endl;
std::cout << " Pos of 33: " << std::endl << array.search_sequential(33) << std::endl;

std::cout << "#---- Searching Binary." << std::endl;
std::cout << " Pos of 33: " << std::endl << array.search_binary(33) << std::endl;

std::cout << "#---- Searching Interpolation." << std::endl;
std::cout << " Pos of 33: " << std::endl << array.search_interpolation(33) << std::endl;

std::cout << "#---- Searching Exponential." << std::endl;
std::cout << " Pos of 33: " << std::endl << array.search_exponential(33) << std::endl;
}

std::cout << "#---- Excercise from slides" << std::endl;
{
SearchArray array;

array.fromVector({10, 14, 33, 41, 45, 59, 73, 82, 90, 101, 118, 119, 134, 141, 150});
std::cout << " Searching Binary." << std::endl;
std::cout << " Pos of 45: " << std::endl << array.search_binary(45) << std::endl;

std::cout << " Comparing interpolation search in two lists." << std::endl;

std::cout << " Searching Interpolation." << std::endl;
std::cout << " Pos of 45: " << std::endl << array.search_interpolation(45) << std::endl;

std::cout << " Loading second array." << std::endl;
array.fromVector({10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 45, 150});
std::cout << " Searching Interpolation." << std::endl;
std::cout << " Pos of 45: " << std::endl << array.search_interpolation(45) << std::endl;
}

return 0;
}
7 changes: 7 additions & 0 deletions src/chapter/04_search/stringsearch/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
add_library(fomstring fomstring.cpp fomstring.h)
set_target_properties(fomstring PROPERTIES PUBLIC_HEADER "fomstring.h")
install(TARGETS fomstring PUBLIC_HEADER DESTINATION include/stringsearch)

add_executable(stringsearch_test stringsearch_test.cpp)
target_link_libraries(stringsearch_test fomstring)
install(TARGETS stringsearch_test DESTINATION bin/c04)
Loading

0 comments on commit be73f8c

Please sign in to comment.