feat: add new Median Search implementation (#1992)

* feat: add new median search algorithm with linked list

* Removed filename

Co-authored-by: David Leal <halfpacho@gmail.com>

* Update search/median_search2.cpp

Co-authored-by: David Leal <halfpacho@gmail.com>

* Update search/median_search2.cpp

Co-authored-by: David Leal <halfpacho@gmail.com>

* Update search/median_search2.cpp

Co-authored-by: David Leal <halfpacho@gmail.com>

* Update search/median_search2.cpp

Co-authored-by: David Leal <halfpacho@gmail.com>

* fix: Requested changes made

* Update search/median_search2.cpp

Co-authored-by: David Leal <halfpacho@gmail.com>

* Update search/median_search2.cpp

Co-authored-by: David Leal <halfpacho@gmail.com>

* Update search/median_search2.cpp

Co-authored-by: David Leal <halfpacho@gmail.com>

* Added algorithm and implementation explanations. Also added wikipedia link.

* Update search/median_search2.cpp

Co-authored-by: David Leal <halfpacho@gmail.com>

* Added @brief and wikipedia link to algo

* Update search/median_search2.cpp

Co-authored-by: David Leal <halfpacho@gmail.com>

* moved includes to top of file

* fix: clang-tidy fixes applied

* fix: clang-tidy fixes

* updating DIRECTORY.md

* clang-format and clang-tidy fixes for b24ca86e

* Update search/median_search2.cpp

Co-authored-by: David Leal <halfpacho@gmail.com>

* clang-format and clang-tidy fixes for 247e0616

* fix: fixed test case failing

* clang-format and clang-tidy fixes for 4c1400db

* fix: test cases now pass

* clang-format and clang-tidy fixes for f3027971

* Update search/median_search2.cpp

Co-authored-by: David Leal <halfpacho@gmail.com>

* Update search/median_search2.cpp

Co-authored-by: David Leal <halfpacho@gmail.com>

* clang-format and clang-tidy fixes for b8b5f5fd

* clang-format and clang-tidy fixes for d67d450c

Co-authored-by: David Leal <halfpacho@gmail.com>
This commit is contained in:
weiss-ben 2022-09-26 19:28:55 +03:00 committed by GitHub
parent 0febbf0314
commit 1645cf281f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 159 additions and 32 deletions

View File

@ -318,6 +318,7 @@
* [Jump Search](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/search/jump_search.cpp) * [Jump Search](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/search/jump_search.cpp)
* [Linear Search](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/search/linear_search.cpp) * [Linear Search](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/search/linear_search.cpp)
* [Median Search](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/search/median_search.cpp) * [Median Search](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/search/median_search.cpp)
* [Median Search2](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/search/median_search2.cpp)
* [Saddleback Search](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/search/saddleback_search.cpp) * [Saddleback Search](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/search/saddleback_search.cpp)
* [Sublist Search](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/search/sublist_search.cpp) * [Sublist Search](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/search/sublist_search.cpp)
* [Ternary Search](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/search/ternary_search.cpp) * [Ternary Search](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/search/ternary_search.cpp)

View File

@ -7,8 +7,8 @@
* @author [Ritika Mukherjee](https://github.com/ritikaa17) * @author [Ritika Mukherjee](https://github.com/ritikaa17)
*/ */
#include <iostream> /// for IO operations #include <cassert> /// for assert
#include <cassert> /// for assert #include <iostream> /// for IO operations
/** /**
* \brief [Algorithm implementation for linear search] * \brief [Algorithm implementation for linear search]
@ -18,17 +18,15 @@
* \returns index where the key-value occurs in the array * \returns index where the key-value occurs in the array
* \returns -1 if key-value not found * \returns -1 if key-value not found
*/ */
int LinearSearch(int *array, int size, int key) int LinearSearch(int *array, int size, int key) {
{ for (int i = 0; i < size; ++i) {
for (int i = 0; i < size; ++i) if (array[i] == key) {
{
if (array[i] == key)
{
return i; return i;
} }
} }
/* We reach here only in case element is not present in array, return an invalid entry in that case*/ /* We reach here only in case element is not present in array, return an
* invalid entry in that case*/
return -1; return -1;
} }
@ -36,12 +34,10 @@ int LinearSearch(int *array, int size, int key)
* @brief Self-test implementations * @brief Self-test implementations
* @returns void * @returns void
*/ */
static void tests() static void tests() {
{
int size = 4; int size = 4;
int *array = new int[size]; int *array = new int[size];
for (int i = 0; i < size; i++) for (int i = 0; i < size; i++) {
{
array[i] = i; array[i] = i;
} }
@ -50,8 +46,7 @@ static void tests()
assert(LinearSearch(array, size, 2) == 2); assert(LinearSearch(array, size, 2) == 2);
size = 6; size = 6;
for (int i = 0; i < size; i++) for (int i = 0; i < size; i++) {
{
array[i] = i; array[i] = i;
} }
@ -60,15 +55,14 @@ static void tests()
assert(LinearSearch(array, size, 5) == 5); assert(LinearSearch(array, size, 5) == 5);
std::cout << "All tests have successfully passed!\n"; std::cout << "All tests have successfully passed!\n";
delete[] array; // free memory up delete[] array; // free memory up
} }
/** /**
* @brief Main function * @brief Main function
* @returns 0 on exit * @returns 0 on exit
*/ */
int main() int main() {
{
int mode = 0; int mode = 0;
std::cout << "Choose mode\n"; std::cout << "Choose mode\n";
@ -76,13 +70,12 @@ int main()
std::cin >> mode; std::cin >> mode;
if (mode == 2) if (mode == 2) {
{
int size = 0; int size = 0;
std::cout << "\nEnter the size of the array [in range 1-30 ]: "; std::cout << "\nEnter the size of the array [in range 1-30 ]: ";
std::cin >> size; std::cin >> size;
while (size <= 0 || size > 30){ while (size <= 0 || size > 30) {
std::cout << "Size can only be 1-30. Please choose another value: "; std::cout << "Size can only be 1-30. Please choose another value: ";
std::cin >> size; std::cin >> size;
} }
@ -92,8 +85,7 @@ int main()
// Input for the array elements // Input for the array elements
std::cout << "Enter the array of " << size << " numbers: "; std::cout << "Enter the array of " << size << " numbers: ";
for (int i = 0; i < size; i++) for (int i = 0; i < size; i++) {
{
std::cin >> array[i]; std::cin >> array[i];
} }
@ -101,19 +93,14 @@ int main()
std::cin >> key; std::cin >> key;
int index = LinearSearch(array, size, key); int index = LinearSearch(array, size, key);
if (index != -1) if (index != -1) {
{
std::cout << "Number found at index: " << index << "\n"; std::cout << "Number found at index: " << index << "\n";
} } else {
else
{
std::cout << "Array element not found"; std::cout << "Array element not found";
} }
delete[] array; delete[] array;
} } else {
else tests(); // run self-test implementations
{
tests(); // run self-test implementations
} }
return 0; return 0;
} }

139
search/median_search2.cpp Normal file
View File

@ -0,0 +1,139 @@
/**
* @file
* @brief Given a linked list L[0,....,n] of n numbers, find the middle node.
*
* @details The technique utilized in this implementation is the ["Floyd's
* tortoise and
* hare"](https://en.wikipedia.org/wiki/Cycle_detection#Floyd's_tortoise_and_hare)
* approach. This technique uses two pointers that iterate through the list at
* different 'speeds' in order to solve problems. In this implementation, for
* every iteration the slow pointer advances one node while the fast pointer
* advances two nodes. The result of this is that since the fast pointer moves
* twice as fast as the slow pointer, when the fast pointer reaches the end of
* the list the slow pointer will be pointing to the middle node of the list.
*
* Here are some example lists you can use to see how the algorithm works
* A = [1,2,3,4,5]
* B = [1,2,3,4,5,6]
* print median(A) #should be 39
* print median(B) #should be 4
*
* @author [Benjamin Weiss](https://github.com/weiss-ben)
* @see median_search.cpp
*/
#include <cassert> /// for assert
#include <iostream> /// for IO operations
/**
* Definition for singly-linked list.
*/
struct ListNode {
int val{0}; ///< the value stored in the node
ListNode* next{nullptr}; ///< pointer to the next node
ListNode() = default; ///< default constructor
explicit ListNode(int x)
: val(x) {} ///< constructor with value for node->val provided
ListNode(int x, ListNode* next)
: val(x),
next(next) {
} ///< constructor with values provided for node->val and node->next
};
/**
* @namespace search
* @brief Search algorithms
*/
namespace search {
/**
* @namespace median_search
* @brief Functions for the Median Search algorithm implementation. Wkipedia
* link to algorithm: https://en.wikipedia.org/wiki/Median_search
*/
namespace median_search2 {
/**
* This function searches for the median of a linked list.
* @param head The head of the linked list.
* @returns Median node of the linked list.
*/
ListNode* middleNode(ListNode* head) {
if (!head) {
return nullptr;
}
// Fast and slow pointers
ListNode* fastptr = nullptr;
ListNode* slowptr = fastptr = head;
// fast jumps 2 while slow jumps 1
while (fastptr->next && fastptr->next->next) {
slowptr = slowptr->next;
fastptr = fastptr->next->next;
}
return (fastptr->next) ? slowptr->next : slowptr;
}
} // namespace median_search2
} // namespace search
/**
* @brief Self-test implementations
* @returns void
*/
static void test() {
auto* head1 = new ListNode;
head1->val = 1;
ListNode* temp = head1;
for (int i = 2; i < 6; ++i) {
// Allocate next
auto* temp1 = new ListNode;
temp1->val = i;
// Advance
temp->next = temp1;
temp = temp1;
}
temp->next = nullptr;
ListNode* median = search::median_search2::middleNode(head1);
assert(3 == median->val); // 3 is the value of the median node.
std::cout << "test case:1 passed\n";
// Test case # 2
auto* head2 = new ListNode;
head2->val = 1;
ListNode* temp2 = head2;
for (int i = 2; i < 7; ++i) {
// Allocate next
auto* temp3 = new ListNode;
temp3->val = i;
// Advance
temp2->next = temp3;
temp2 = temp3;
}
temp2->next = nullptr;
ListNode* median1 = search::median_search2::middleNode(head2);
assert(4 == median1->val); // 4 is the value of the median node.
std::cout << "test case:2 passed\n";
delete head1;
delete temp;
delete head2;
delete temp2;
std::cout << "--All tests passed--\n";
}
/**
* @brief Main function
* @returns 0 on exit
*/
int main() {
test(); // run self-test implementations
return 0;
}