簡體   English   中英

遞歸查找數組中的最小值和最大值

[英]Recursively find min and max value in array

我做了一個遞歸函數,以從可能包含任意數量元素的數組中找到最大值和最小值。 這樣做的主要原因是想出一種從Dicom圖像的像素數據中找到最小值最大值的想法。 我將此遞歸函數用作測試代碼,在其中用0至1000的隨機數填充了一個int類型的數組。 我的代碼如下。 我提供了完整的代碼,您可以在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;
}

我對您的問題是,您認為我的算法可以正常工作嗎? 我有些懷疑。 另外,我是否正確處理或維護內存? 否則代碼中會內存泄漏?

您應該使用delete [] newMax; 最后一個if語句,否則您將永遠不會釋放內存。 像這樣:

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

與recursMin函數相同。

您的算法似乎可行,但過度。 僅使用遞歸和分配內存來查找最小值和最大值不是一種好方法。

我建議此代碼用於查找最小值,最大值類似:

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

短得多,沒有內存分配,容易循環,因此編譯器可能會1)將其向量化以達到最大速度2)使用正確的預取以提高速度。

對於最大值,我將使用類似以下的方法:

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可以使用相同的模式輕松實現。

只是部分答案,因為我尚未詳細驗證算法,但是最好先復制數組,然后破壞性地使用該副本存儲您的值。
它可能會使用更多的內存,但是可以節省內存管理的運行時和錯誤追蹤時間。

如果您冒着陷入難以解決的情況而導致太深的遞歸的風險,則可以通過迭代實現而不是遞歸實現來改進。

這是找到最小值和最大值的可怕算法。 您可以使用更簡單,更短和更快的解決方案:

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

使用STL中的算法:

  • 從C ++ 11開始:您可以使用std::minmax_element一次檢索兩者: https std::minmax_element

     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

基本上,遞歸建議不要在數組中找到max,因為這不是必需的。 分而治之的算法(遞歸)花費的時間更多。 但是,即使您想使用它,也可以使用下面的算法。 基本上,它在第一位置帶來了數組的最大元素,並且運行時間幾乎是線性的(盡管這種算法只是遞歸的錯覺!):

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

      } 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM