As for other recursive functions, it suffices to implement the simplest case and call the same function with a smaller task:
template<class ForwardIt> ForwardIt max_element(ForwardIt first, ForwardIt last, ForwardIt largest) { if (first == last) // no more elements to compare return largest; if (*largest < *first) // compare with the first element largest = first; ++first; return max_element(first, last, largest); // compare the rest }
if the word template not clear, then in order not to be distracted (this is not important for understanding recursion), you can simply replace ForwardIt with float* .
The simplest case here is an empty array ( first == last ), in which case the function simply returns the largest argument.
To reduce the size of the task, you can drop the first element first updating the largest if necessary — and call the function recursively with the input residuals to complete the task.
For ease of use, you can define a function with two parameters, passing first as the initial value for the largest — this also works for empty arrays; in this case, a value of last is returned:
template<class ForwardIt> ForwardIt max_element(ForwardIt first, ForwardIt last) { return max_element(first, last, first); }
Example of use:
#include <iostream> int main() { float a[] = {1, -2, 3, 0.5}; std::cout << *max_element(a, a + sizeof(a) / sizeof(*a)) << '\n'; }
To start it:
$ g++ max_recursive.cc && ./a.out 3
In this case, max_element() is the so-called tail-recursive function — the recursive call is the tail (last) in the function and may not consume the stack. Some compilers can automatically convert such code into loops, for example, gcc -O2 for ForwardIt=int* can generate such an assembler :
# first : %rdi # last : %rsi # largest: %rdx # result : %rax max_element(int*, int*, int*): cmpq %rsi, %rdi # x = cmp(first, last) movq %rdx, %rax # result = largest je .L2 # if(first == last) return result // if(!x) .L4: # do { movl (%rdi), %ecx # y = *first cmpl %ecx, (%rax) # z = cmp(*result, y) cmovl %rdi, %rax # if (*result < y) result = first //if(z<0) addq $4, %rdi # ++first cmpq %rdi, %rsi # x = cmp(last, first) jne .L4 # } while (last != first) // while(x) .L2: rep ret # return result // rep is amd // brancher bug workaround
Absolutely the same code is obtained from the iterative version :
int* max_element(int* first, int* last, int* largest) { for ( ; first != last; ++first) if (*largest < *first) largest = first; return largest; }
std::maprecursive search for a minimum / maximum is very convenient. What is your data storage structure? And give at least an attempt to implement the search. - StateItPrimitive