0

I made a recursive function to find the max and min value from an array which may contain arbitrary number of elements. The main reason behind making this was to develop an idea in finding the min max value from the pixel data of a Dicom image. I made this recursive function as a test code where I filled an int type array with random numbers ranging from 0-1000. My code is as below. I presented the whole code, you can run the program very easily in Visual Studio yourself.

#include <stdio.h>
#include <string>
#include <iostream>
#include <math.h>
#include <time.h>
using  namespace std;

void recursMax(int* a, int size, int* maxValue)
{
    int half = size/2;
    int* newMax = new int[half];
    for(int i=0; i<half; i++)
    {
        newMax[i]=a[i]>a[size-i-1]?a[i]:a[size-i-1];
    }
    if(half>1)
    {
        recursMax(newMax, half, maxValue);
    }
    if(half == 1)
    {
        *maxValue = newMax[0];
        delete [] newMax;
    }
}

void recursMin(int* a, int size, int* minValue)
{
    int half = size/2;
    int* newMin = new int[half];
    for(int i=0; i<half; i++)
    {
        newMin[i]=a[i]<a[size-i-1]?a[i]:a[size-i-1];
    }

    if(half>1)
    {
        recursMin(newMin, half, minValue);
    }
    if(half == 1)
    {
        *minValue = newMin[0];
        delete [] newMin;
    }
}

int main ()
{
    int size = 100;
    int* a = new int[size];
    srand(time(NULL));
    for(int i=0; i<size; i++)
    {
        a[i]=rand()%1000;
        cout<<"Index : "<<i+1<<",  "<<a[i]<<endl;
    }
    cout<<endl<<endl<<"Now we look to find the max!"<<endl;
    int maxValue = 0;
    int minValue = 0;
    recursMax(a, size, &maxValue);
    cout<<maxValue<<endl;
    recursMin(a, size, &minValue);
    cout<<"Now we look for the min value!"<<endl<<minValue<<endl;
    cout<<"Checking the accuracy! First for Max value!"<<endl;
    for(int i=0; i<size; i++)
    {
        cout<<"Index : "<<i+1<<",  "<<maxValue-a[i]<<endl;
    }
    cout<<"Checking the accuracy! Now for min value!"<<endl;
    for(int i=0; i<size; i++)
    {
        cout<<"Index : "<<i+1<<",  "<<a[i]-minValue<<endl;
    }
    delete [] a;
    return 0;
}

My question to you is that, do you think my algorithm works correctly? I'm have some doubt. Also, am I handling or maintaining the memory correctly? Or there will be some memory leakage in the code?

Engineer2021
  • 3,288
  • 6
  • 29
  • 51
the_naive
  • 2,936
  • 6
  • 39
  • 68
  • If half is never equal 1, then you could leak `newMin` array. Since you are dividing by 2, it may be possible that it never reaches 1. Plus it seems like you are allocating over and over every time recursMax is called. So that when it is unrolled, that delete[] may not be hit. Same thing for recursMin. – Engineer2021 Mar 20 '14 at 11:56
  • allocating memory just to find the minimum in an array is a quite bad idea. Why not simply loop over the array and to find the minimum? – gexicide Mar 20 '14 at 11:58
  • @GIJoe Half does equals to 1 at the final stage! I checked it! – the_naive Mar 20 '14 at 11:58
  • @gexicide What should I do then? – the_naive Mar 20 '14 at 11:59
  • @the_naive: Sure, but you are allocating it N times and deallocating it once? – Engineer2021 Mar 20 '14 at 11:59
  • @GIJoe Exactly! That's why I think there's memory leakage, but I can't find a better approach! – the_naive Mar 20 '14 at 12:01
  • See here.. no extra allocation - https://stackoverflow.com/questions/18418680/recursion-how-to-find-minimum-value-of-a-array – Engineer2021 Mar 20 '14 at 12:03
  • 1
    Recursion really isn't the best way to implement this in C++. You expose yourself to the the chance of running out of stack space when processing a large array, so you should go with a procedural approach. – Sean Mar 20 '14 at 12:12
  • @gexicide Because it runs in logarithmic time instead of linear. It's basically the partitioning part of quicksort. – molbdnilo Mar 20 '14 at 12:12

7 Answers7

2

You should take delete [] newMax; out of last if statement, otherwise you'll never free memory. Like this:

if(half == 1)
{
    *maxValue = newMax[0];
}
delete [] newMax;

And the same for recursMin function.

Your algorithm seems working, but excessive. Using recursion and allocating memory just to find min and max is not a good style.

Ryzhehvost
  • 395
  • 1
  • 9
  • I wanted to do that, but I feared that `delete [] newMax;` may lead to heap error. Apparently there's no heap error, I changed the code, and it seems working fine. – the_naive Mar 20 '14 at 12:19
1

I would suggest this code for finding the minimum, maximum is similar:

int min = std::numeric_limits<int>::max();
for(int i = 0; i < size ; i++) min = std::min(min,a[i]);

A lot shorter, no memory allocation, easy loop so the compiler will probably 1) vectorize it for maximum speed 2) use correct prefetching for even higher speed.

user1767754
  • 23,311
  • 18
  • 141
  • 164
gexicide
  • 38,535
  • 21
  • 92
  • 152
  • The first line gives the error `a value of type "int (__cdecl *)()" cannot be used to initialize an entity of type "int"`. – the_naive Mar 20 '14 at 12:09
  • The first line should be `int min = std::numerical_limits::max();`. Thanks anyways. – the_naive Mar 20 '14 at 12:20
  • Nice answer, but not quite accurate! Instead of `int min = std::numerical_limits::max;`, we should do `int min = a[0]`. Otherwise the min will the be min value of `int` type. – the_naive Mar 20 '14 at 12:28
  • @the_naive: a[0] is fine as well, but max is fine too. Please regard that I use `max`, *not* `min`! – gexicide Mar 25 '14 at 11:55
1

For the max value I'd go with something like this:

int ArrayMax(const int *begin, const int *end)
{
  int maxSoFar = *begin;  // Assume there's at least one item

  ++begin;

  for(const int *it = begin; it!=end; ++it)
  {
    maxSoFar = std::max(maxSoFar, *it);
  }

  return maxSoFar
}

Now you can say:

int main ()
{
  int size = 100;
  int* a = new int[size];
  srand(time(NULL));
  for(int i=0; i<size; i++)
  {
    a[i]=rand()%1000;
    cout<<"Index : "<<i+1<<",  "<<a[i]<<endl;
  }

  int theMax = ArrayMax(a, a+size);
}

Needless to say, you can convert ArrayMax into a template function to take any type, and ArrayMin is easily implemented using the same pattern.

Sean
  • 60,939
  • 11
  • 97
  • 136
  • Thanks for the answer! My mistake was that I didn't know `std`has a max function! But of all the suggested approach I like it the most! – the_naive Mar 20 '14 at 12:26
0

Only a partial answer because I haven't verified the algorithm in detail, but you're much better off copying the array first, then using that copy destructively to store your values.
It might use more memory, but saves you both runtime and bug chasing time on memory management.

You could probably improve things with an iterative implementation rather than a recursive one, if you risk running into degerate case that cause too deep recursion.

molbdnilo
  • 64,751
  • 3
  • 43
  • 82
0

This is terrible algorithm for finding minimum and maximum. You can use simpler, shorter and faster solution:

const int maxInArray( const int* beg, const int* end) {
const int* it  = std::max_element( beg, end);
    if ( it == end)
    {
        std::cout << "There is no smallest element" << std::endl;
    }
    else
    {
        std::cout << "The smallest element is " << *it << std::endl;
    }
return *it;
}

or iterate over the array:

int maxInArray( const int* beg, const int* end) {
    int max;
    if ( end - beg < 1 ) return -1;
    max = *beg
    while ( beg++ != end) {
        if ( *beg > max) max = *beg;
    }
    return max;
}

with no boost support:

#include <iostream>
#include <limits>

int main() {
    int max = std::numeric_limits<int>::min();
    int min = std::numeric_limits<int>::max();
    int num;

    while ( std::cin >> num) {
            if (num > max) {
                max = num;
            }
            if (num < min) {
                min = num;
            }
    }
    std::cout << "min: " << min << std::endl;
    std::cout << "max: " << max << std::endl;

    return 0;
}

or with help from boost:

#include <iostream>
#include <boost/accumulators/accumulators.hpp>
#include <boost/accumulators/statistics/stats.hpp>
#include <boost/accumulators/statistics/min.hpp>
#include <boost/accumulators/statistics/max.hpp>
using namespace boost::accumulators;


int main() {
    // Define an accumulator set for calculating the mean, max, and min
    accumulator_set<double, features<tag::min, tag::max> > acc;

    int num = -1;
    bool empty = true;

    while ( std::cin >> num && num >= 0) {
        empty = false;
        acc( num);
    }

    if ( ! empty) {
        // Display the results ...
        std::cout << "Min: " << min( acc) << std::endl;
        std::cout << "Max: " << max( acc) << std::endl;  
    }

    return 0;
}
4pie0
  • 29,204
  • 9
  • 82
  • 118
0

Using algorithm from STL:

  • Since C++11: you may use std::minmax_element to retrieve both at once : https://ideone.com/rjFlZi

    const int a[] = {0, 1, 42, -1, 4};
    
    auto it = std::minmax_element(std::begin(a), std::end(a));
    std::cout << *it.first << " " << *it.second << std::endl;
    
  • In C++03, you may use std::min_element and std::max_element.

Jarod42
  • 203,559
  • 14
  • 181
  • 302
-1

Basically finding max in array is not recommended by recursion as it is not required. Divide and conquer algorithms(recursive) are more time costly. But even though if you want to use it, you can use my below algorithm. Basically, it brings the largest element of array at first position and has almost linear running time.(This algo is just a recursive-illusion though!):

    int getRecursiveMax(int arr[], int size){
      if(size==1){
                  return arr[0];
      }else{
             if(arr[0]< arr[size-1]){
                                  arr[0]=arr[size-1];
                 }
             return(getRecursiveMax(arr,size-1));
        }

      } 
  • Please don't simply copy and paste your [answer](http://stackoverflow.com/a/35543895/189134) to multiple questions. Ensure that your post answers the question being asked and you aren't simply pasting your answer in multiple places without actually answering the question. – Andy Feb 22 '16 at 04:20
  • Hi Andy, Thanks for the suggestion! :-) But I just wrote this to answer this question too. There can be two functions getRecursiveMax() and getRecursiveMin(). One has to replace > sign with < and one can find max and min both. I didnt write the other function as I think its understood. – Rajveer Sidhu Feb 23 '16 at 14:32