Explain how recursion works here, because I don’t really understand:

#include <stdio.h> #include <stdlib.h> #include <iostream.h> #include <conio.h> int maxs(double*, int); int _tmain(int argc, _TCHAR* argv[]) { randomize(); double n; int i; cin >> n; double* a = new double[n]; for (i = 0; i < n; i++) *(a + i) = random(21) - 10; for (i = 0; i < n; i++) cout << *(a + i) << " "; cout << endl; double r = maxs(a, n - 1); cout << "Max value is " << r; getch(); return 0; } int maxs(double* a, int n) { double r1, r2; if (n == 0) return a[0]; r1 = maxs(a, n / 2); r2 = maxs(a + n / 2 + 1, n - 1); return max(r1, r2); } 
  • Why don't you ask the person who provided this incorrect code? :) - Vlad from Moscow
  • how to say it, oh yeah, it works - Alex Stepanov
  • Start by reading this th-algoritmov.narod.ru/8.htm - your code is as close as possible to Fibonacci. - KoVadim

1 answer 1

Your whole program code is not correct.

First, the size of the array must be of type integer. Otherwise, the number of selected elements for the array and the cycles used to fill it may not match each other.

For example, suppose that the value of the variable n is 1.5 . Then an array consisting of 1 element is selected, since the fractional part of the number will be discarded. However, in this cycle

 for(i=0;i<n;i++) *(a+i)=random(21)-10; 

will have two iterations for the values ​​of the variable i equal to 0 and 1, since both of these values ​​are less than 1.5. As a result, the array element will be addressed with index 1, which does not exist. Therefore, the program has an undefined behavior.

The function is also not correct.

In the body of the function, an object of type double returned, which will be converted to type int , since this is the return type of the function. Therefore, the function returns an incorrect value if the returned object has a fractional part.

 int maxs(double *, int ); ^^^ 

When calling a function, it is not clear why the size of the array decreases.

 maxs(a,n-1); ^^^^ 

Therefore, the number of elements in the function will be incorrectly considered.

In these offers

 r1=maxs(a,n/2); r2=maxs(a+n/2+1,n-1); 

ideas are looking for the maximum elements of the two halves of the array. However, the number of elements of the array in the second half is considered not true

 r2=maxs(a+n/2+1,n-1); ^^^^ 

This function also has undefined behavior.

You can easily verify this yourself by running such a simple example.

 #include <iostream> #include <algorithm> int maxs (double *a,int n){ double r1,r2; if(n==0) return a[0]; r1=maxs(a,n/2); r2=maxs(a+n/2+1,n-1); return std:: max(r1,r2); } int main() { double a[] = { 1.1, 2.2, 3.3, 100.123 }; std::cout << maxs( a, 2 ) << std::endl; } 

In this program, the function is started for a subarray consisting of elements 1.1, 2.2, 3.3, since the second parameter is 2. However, the function returns the number 100 (not even 100.123) instead of the correct value 3.3.

It will be correct to write a function so that it returns the index of the maximum element. Then, for an empty array, the function returns an index equal to the length of the array, that is, 0, and thus allows to distinguish whether a real array is passed to the function, or an empty array.

Here's how the function might look

 size_t max_element( const double *a, size_t n ) { if ( n < 2 ) { return 0; } else { size_t i = max_element( a, n / 2 ); size_t j = n / 2 + max_element( a + n / 2 , n - n / 2 ); return a[i] < a[j] ? j : i; } } 

First, it checks how many elements are in the array, that is, less than 2 or not. If there are less than two elements in the array, that is, either the array consists of one element or is empty, then the index of this element is returned.

Otherwise, the array is divided into two halves: elements with indices less than n / 2 and elements with indices starting from n /2 to n . And the function is recursively called for each of the halves of the original array. Then, on the basis of the maximum elements indexes returned from the function calls for each half of the array, these two maximum elements are compared and the index of the highest one in turn is returned from the function.

Here is a demo program in which your original function and the function I proposed are called for a subarray of three elements

 #include <iostream> #include <algorithm> size_t max_element( const double *a, size_t n ) { if ( n < 2 ) { return 0; } else { size_t i = max_element( a, n / 2 ); size_t j = n / 2 + max_element( a + n / 2 , n - n / 2 ); return a[i] < a[j] ? j : i; } } int maxs (double *a,int n){ double r1,r2; if(n==0) return a[0]; r1=maxs(a,n/2); r2=maxs(a+n/2+1,n-1); return std:: max(r1,r2); } int main() { double a[] = { 1.1, 2.2, 3.3, 100.123 }; std::cout << maxs( a, 2 ) << std::endl; std::cout << a[max_element( a, 3 )] << std::endl; } 

Output of the program to the console

 100 3.3 

As you can see from the output, your function returns a value that is not even included in the {1.1, 2.2, 3.3} subarray, while the second function returns the correct value 3.3 .

The function is simple. Suppose there is an array of four elements {a [0], a [1], a [2], a [3]}. The function is called with the address of the first array element and the number of elements.

 max_element( a, 4 ) 

In its body, the function calls itself for the subarrays {a [0], a [1]} and {a [2], a [3]} as follows

 max_element( a, 2 ) <== max_element( a, n / 2 ) 

and

 max_element( a + 2, 2 ) <== max_element( a + т . 2, т - n / 2 ) 

That is, the maximum element of the entire array of the array is searched for as the largest value of the two halves of the array.

 a[0] a[1] a[2] a[3] | | | | ------ ------ max1 max2 | | ------------ max 

Each recursive function call returns the index of the maximum element in the subarray by dividing the source array into two halves. In function, these indices are designated by variables i and j

So, after a recursive call, we get two indexes of maximal elements respectively for the first half of the array and for the second half of the array.

 size_t i = max_element( a, n / 2 ); size_t j = n / 2 + max_element( a + n / 2 , n - n / 2 ); 

Then we compare these maximal elements of each of the halves corresponding to the obtained indices and ultimately return from the function the index of that element of these two, which is the maximum

 return a[i] < a[j] ? j : i; 
  • An experienced QA will of course introduce 1.5 and -10 (by the way, for some reason this option has not been considered). But the author of the question understands that there the number of elements and introduces the number of elements (that is, an integer). Therefore, a cast is permissible. And even the conditions will be fulfilled normally. But the TC asked something not about that. - KoVadim
  • @KoVadim The author of the question obviously does not understand what he is doing, and therefore introduces a floating point variable for the number of elements in the array. - Vlad from Moscow
  • By the way, in one of the examples - two errors. The code doesn't even compile. The author of the question does not ask about errors, about how recursion works. - KoVadim
  • I do not deny that my code is not perfect and is even buggy. And the matter is not at all in this. @VladfromMoscow I ask you, unless of course it doesn’t make it difficult for you to "chew like a baby", explain step by step how your (exactly your) recursive function works. I am very grateful. maximum item. - Alex Stepanov
  • one
    @KoVadim The author asks about a specific function that is incorrect and has undefined behavior. Therefore, to tell how it "works." when it does not work, it is meaningless. - Vlad from Moscow