2014-01-16 2 views
0

Я пытаюсь вернуть максимальный элемент из массива с помощью рекурсии
вот мой кодне может вернуть максимальный элемент

static void Main(string[] args) 
    { 
     int[] Array=new int[]{10,233,34}; 

     int _MaxVal = CalculateMax(Array, 0, 0); 
     Console.WriteLine(_MaxVal); 
     Console.ReadKey(); 

    } 

    private static int CalculateMax(int[] Array, int Startpos, int maxval) 
    { 
     if (Startpos != Array.Length) 
     { 
      if (Array[Startpos] > maxval) 
      { 
       maxval = Array[Startpos]; 
      } 


      CalculateMax(Array, ++Startpos, maxval); 
     } 

     return maxval; 
    } 

Я получаю MAXVAL как 10.

Что в этом плохого?

Спасибо всем

+0

Вы также хотите выполнить 'maxval = CalculateMax (Array, ++ Startpos, maxval);'? – Jonny

+0

Вы не принимаете во внимание возвращаемое значение 'CalculateMax()', когда вы вызываете его рекурсивно. –

+0

Вы знаете, что можете сделать '= Array.Max()', правильно? –

ответ

7

Вы теряете значение maxval.

Попробуйте это:

maxval = CalculateMax(Array, ++Startpos, maxval); 

Если вы делаете это в качестве личного упражнения или для назначения, вы могли бы справиться с этим путь более изящно LINQ:

var maxValue = Array.Max(); 
+1

+1. Я бы также добавил, что было бы лучше иметь начальное значение для 'maxval'' int.MinValue', так как иначе максимальное значение меньше нуля, результат будет неправильным. (То, что должно быть сделано, если массив пуст, - это другой вопрос). –

1

Чтобы использовать рекурсии, вы должны иметь стоп-тест и обязательно начинайте следующий шаг по ошибке .

Попробуйте это: (Не уверен, что если Array.SubArray (целое) является вещественной функцией, но это идея

static void Main(string[] args) 
{ 
    int[] Array=new int[]{10,233,34}; 

    int _MaxVal = CalculateMax(Array); 
    Console.WriteLine(_MaxVal); 
    Console.ReadKey(); 

} 

private static int CalculateMax(int[] Array) 
{ 
    if (Array.Length > 0) 
    { 
     int maxSubArray = CalculateMax(Array.SubArray(1)); // Use recursive function on the SubArray starting at index 1 (that the smaller problem) 
     if (maxSubArray > Array[0]) 
     { 
      return maxSubArray; 
     } else { 
      return Array[0]; 
     } 

    } else { 
     return 0; // Stop test 
    } 
} 

Примечание:. Он не будет работать с отрицательным значением

0
static void Main(string[] args) 
    { 
     int[] Array = new int[] { 10, 233, 34 }; 

     int _MaxVal = CalculateMax(Array); 
     Console.WriteLine(_MaxVal); 
     Console.ReadKey(); 

    } 
    private static int CalculateMax(int[] Array) 
    { 
     int max = 0; 
     for (int i = 0; i < Array.Length; i++) 
      if (Array[i] > max) 
       max = Array[i]; 
     return max; 
    } 
.

ИЛИ

var max1 = Array.Max(); 
var max2 = Array.Concat(new[] { 0 }).Max(); 
var max3 = Array.OrderByDescending(p => p).FirstOrDefault(); 
-1

Вы не используете возвращаемое значение из гее ursive call. Это:

CalculateMax(Array, ++Startpos, maxval); 

должно быть:

maxval = CalculateMax(Array, ++Startpos, maxval); 

Во всяком случае, вы используете рекурсию вместо цикла, который является очень плохим способом использовать рекурсию. Вы будете делать рекурсию настолько глубоко, что в массиве есть элементы, что означает, что у вас очень медленный цикл, и вы получите переполнение стека, если массив слишком велик.

Чтобы правильно использовать рекурсию, вы должны разделить работу на более мелкие части и использовать рекурсию для обработки меньших частей, пока части не будут настолько малы, что они тривиальны.

Например, разделить массив пополам для каждого уровня:

int[] Array = new int[]{ 10, 233, 34 }; 
int _MaxVal = CalculateMax(Array, 0, Array.Length); 
Console.WriteLine(_MaxVal); 

private static int CalculateMax(int[] array, int start, int length) { 
    if (length == 1) { 
    return array[start]; 
    } else { 
    int half = length/2; 
    int first = CalculateMax(array, start, half); 
    int second = CalculateMax(array, start + half, length - half); 
    return first > second ? first : second; 
    } 
} 
+1

Это не плохой способ использования рекурсии, использование рекурсии в конце функции может быть оптимизировано для цикла и является общим шаблоном http://en.wikipedia.org/wiki/Tail_call – Hogan

+0

@Hogan: C# doesn ' t рекурсия хвоста: http://stackoverflow.com/questions/491376/why-doesnt-net-c-optimize-for-tail-call-recursion – Guffa

+1

Немного устаревший - http://blogs.msdn.com/ b/clrcodegeneration/archive/2009/05/11/tail-call-improvement-in-net-framework-4.aspx – Hogan

0

Вы не использовать возвращаемое значение из более глубоких вызовов CalculateMax

Изменения

CalculateMax(Array, ++Startpos, maxval); 

в

maxval = CalculateMax(Array, ++Startpos, maxval); 

Таким образом, вы пропускаете maxval не только вперед, но и назад к главному().

Как уже упоминалось ранее, рекурсия не лучший способ сделать это, потому что может произойти переполнение стека.

Смежные вопросы