-
-
Notifications
You must be signed in to change notification settings - Fork 7.3k
/
median_search2.cpp
142 lines (125 loc) · 3.89 KB
/
median_search2.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
/**
* @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;
}
void deleteAll(const ListNode* const head) {
if (head) {
deleteAll(head->next);
delete head;
}
}
} // 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;
const ListNode* const median = search::median_search2::middleNode(head1);
assert(3 == median->val); // 3 is the value of the median node.
search::median_search2::deleteAll(head1);
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;
const ListNode* const median1 = search::median_search2::middleNode(head2);
assert(4 == median1->val); // 4 is the value of the median node.
search::median_search2::deleteAll(head2);
std::cout << "test case:2 passed\n";
std::cout << "--All tests passed--\n";
}
/**
* @brief Main function
* @returns 0 on exit
*/
int main() {
test(); // run self-test implementations
return 0;
}