以递归方式查找数组中的最小值和最大值

时间:2014-03-20 11:54:30

标签: c++ memory-management recursion

我做了一个递归函数,从一个可能包含任意数量元素的数组中找到max和min值。实现这一目标的主要原因是开发了一个从Dicom图像的像素数据中找到最大最大值的想法。我将这个递归函数作为测试代码,在其中填充int类型数组,随机数范围为0-1000。我的代码如下。我展示了整个代码,您可以自己在Visual Studio中轻松运行该程序。

#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;
}

我的问题是,您认为我的算法是否正常工作?我有一些疑问。我还在正确处理或维护内存吗?或者代码中会有一些内存泄漏?

7 个答案:

答案 0 :(得分:2)

你应该从delete [] newMax;语句中取出if,否则你永远不会释放记忆。像这样:

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

对于recursMin函数也一样。

您的算法似乎有效,但过度。使用递归和分配内存只是为了找到最小值和最大值并不是一种好的风格。

答案 1 :(得分:1)

我建议使用此代码查找最小值,最大值类似:

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

更短,没有内存分配,易于循环,因此编译器可能1)将其矢量化以获得最大速度2)使用正确的预取以获得更高的速度。

答案 2 :(得分:1)

对于最大值,我会选择以下内容:

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
}

现在你可以说:

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);
}

毋庸置疑,您可以将ArrayMax转换为模板函数以采用任何类型,ArrayMin可以使用相同的模式轻松实现。

答案 3 :(得分:0)

只是部分答案,因为我还没有详细验证算法,但您最好首先复制数组,然后破坏性地使用该副本来存储您的值。
它可能会占用更多内存,但可以节省运行时和内存管理上的bug追踪时间。

如果您冒险进入导致过深递归的degerate案例,您可能可以使用迭代实现而不是递归实现来改进事物。

答案 4 :(得分:0)

这是查找最小值和最大值的可怕算法。您可以使用更简单,更短,更快的解决方案:

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;
}

或迭代数组:

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;
}

没有助力支持:

#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;
}

或在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;
}

答案 5 :(得分:0)

使用STL的算法:

  • 从C ++ 11开始:您可以使用std::minmax_element一次检索两者: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;
    
  • 在C ++ 03中,您可以使用std::min_elementstd::max_element

答案 6 :(得分:-1)

基本上不建议在递归中找到max in array,因为它不是必需的。划分和征服算法(递归)的时间成本更高。但即使你想使用它,你也可以使用我的下面的算法。基本上,它在第一个位置带来了阵列中最大的元素,并且具有几乎线性的运行时间。(这个算法只是一个递归错觉!):

    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));
        }

      }