mirror of
https://hub.njuu.cf/TheAlgorithms/C-Plus-Plus.git
synced 2023-10-11 13:05:55 +08:00
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 forb24ca86e
* Update search/median_search2.cpp Co-authored-by: David Leal <halfpacho@gmail.com> * clang-format and clang-tidy fixes for247e0616
* fix: fixed test case failing * clang-format and clang-tidy fixes for4c1400db
* fix: test cases now pass * clang-format and clang-tidy fixes forf3027971
* 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 forb8b5f5fd
* clang-format and clang-tidy fixes ford67d450c
Co-authored-by: David Leal <halfpacho@gmail.com>
This commit is contained in:
parent
0febbf0314
commit
1645cf281f
@ -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)
|
||||||
|
@ -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
139
search/median_search2.cpp
Normal 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;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user