метод рекурсии продолжает давать сбой (алгоритм изменения)

#c #algorithm #recursion

#c #алгоритм #рекурсия

Вопрос:

 //amt = amount of cents to get change for
//onhand = array of available coins . Ex: {3, 0, 1, 0} = 3 quart, 0 dime, 1 nickel, 0 pennies

//denoms = {25, 10, 5, 1}

//ndenoms = 4 ; i.e the number of different denominations

// thechange = array of change. Ex: if amt = 80, then one possible thechange = {3, 0, 1, 0} b/c 3*25   1*5 = 80 cents



int i = 0;

void makechange(int amt, int *onhand, int *denoms, int ndenoms, int *thechange)
   {            

      if ( (denoms[i] * onhand[i]) > amt)
         {
                    onhand[i]--;    // # of coins is too much, decrement and try again
                    makechange(amt, onhand, denoms, ndenoms, thechange); // try agan
         }

      thechange[i] = onhand[i]; //found #of coins

      amt = amt - denoms[i]*onhand[i]; // get remaining amount from change
      i  ;

      if (amt != 0) // we're not done with change so move on to next denomination
      {
           makechange(amt, onhand, denoms, ndenoms, thechange);
      }   


      else if (amt == 0) // we're done with the change so all the other # coins = 0
      {
           for (int j = i; j < amt; j  )
             {
              thechange[j] = 0;
             }
      }




   }   






Now, down in main when I actually call the function prototype and print out the result

//


makechange(amt, onhand, denoms, ndenoms, thechange);

  for (int k = 0; k < ndenoms; k  )
  {
      cout << thechange[i] << " ";
  }


//
  

Я получаю сообщение об ошибке.

Этот алгоритм кажется мне разумным, кто-нибудь знает, почему он продолжает сбоить?

Правильно ли я использовал рекурсию здесь?

Комментарии:

1. Как происходит сбой? Вы получаете сообщение об ошибке, когда это происходит? И что это за язык?

2. Я использую C и компилирую с devc

3. Всякий раз, когда я компилирую и запускаю, я получаю «change.exe перестал работать » итак, я предполагаю, что ошибка seg или что-то в этом роде?

4. Тег изменен на c для согласованности с языком и компилятором, используемым OP

Ответ №1:

Если вы вызовете makechange дважды, во второй раз это не сработает, потому что глобальная переменная i будет неправильной.

Также, что должно произойти, если вы попытаетесь makechange и у вас недостаточно изменений для этого?

Аналогично, что произойдет, если у вас есть 3 четвертака и 3 десятицентовика, и вас просят внести 80 центов сдачи? Ваш алгоритм будет использовать все 3 квартала, а затем застрянет.

Комментарии:

1. @ted-stevens: Ваш алгоритм предполагает, что i начинается с 0. Если вы makechange уже вызывали, значение больше не равно 0, и вы никогда не увидите свое первое обозначение.

Ответ №2:

вы имели в виду

 for (int k = 0; k < ndenoms; k  ) { cout << thechange[k] << " "; }
  

небольшая опечатка стала возможной благодаря использованию глобальной переменной i.

также

       for (int j = i; j < amt; j  ) { thechange[j] = 0; }
  

Я думаю, вы имели в виду

 for (int j = i; j < ndenoms; j  )
  

в зависимости от конечного значения amt это приведет к завершению работы с концом массива, что приведет к сбою.

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

 int makechange(int amt, int *onhand, int *denoms, int ndenoms, int *thechange)
{
for (int i=0; i < ndenoms amp;amp; amt > 0; i ) { while (onhand[i] > 0 amp;amp; denoms[i] <= amt) { onhand[i]--; // use one coin thechange[i] ; amt -= denoms[i]; } } return amt; // this is the amount you owe if you dont have enough on hand }


Комментарии:

1. ^ спасибо, но даже после этого он все еще вылетает. Кто-нибудь может скопировать и вставить мой код и попробовать его, пожалуйста?

2. Попробуйте добавить операторы печати при входе и выходе из makechange. Возможно, вы поймете, что не так, когда сможете увидеть контекст сбоя.

3. также вы не проверяете наличие i> = ndenoms в качестве условия выхода. Вы можете вывести нижний индекс за пределы диапазона после последнего i , если не будете осторожны.

4. ^ Почему алгоритм зацикливается вечно?

5. Мне не нужна инструкция exit, не так ли? Функция больше не будет вызывать себя один раз (amt == 0) и завершать остальную часть main. Так разве этого недостаточно?

Ответ №3:

Я внес изменения, упомянутые shsmith, и вот модифицированная и полная программа на c .

 #include <iostream> 
  

using namespace std;

int i = 0;

 void makechange(int amt, int *onhand, int *denoms, int ndenoms, int *thechange)
{
    if ( (denoms[i] * onhand[i]) > amt)
    {
            onhand[i]--;    // # of coins is too much, decrement and try again
            makechange(amt, onhand, denoms, ndenoms, thechange); // try agan
    }

    thechange[i] = onhand[i]; //found #of coins
    amt = amt - denoms[i]*onhand[i]; // get remaining amount from change
    i  ;
    if (amt != 0) // we're not done with change so move on to next denomination
    {
            makechange(amt, onhand, denoms, ndenoms, thechange);
    }
    else if (amt == 0) // we're done with the change so all the other # coins = 0
    {
            for (int j = i; j < ndenoms; j  )
            {
                    thechange[j] = 0;
            }
    }}
  

int main(){

     //Now, down in main when I actually call the function prototype and print out the result
    int amt = 80, onhand[] = {3, 0, 1, 0}, denoms[] = {25, 10, 5, 1}, ndenoms = 4, thechange[4];
    makechange(amt, onhand, denoms, ndenoms, thechange);
    for (int k = 0; k < ndenoms; k  )
    {
            cout << thechange[k] << " ";
    }
    cout << "n";
    return 0;}
  

Этот код отлично работает на моей машине. Я скомпилировал его с помощью Cygwin.

Примечание: Этот алгоритм будет работать, только если у вас есть монеты номинала более или менее корректно на руках. Если в наличии недостаточно монет, то у рекурсивного метода нет выхода, потому что 'amt' никогда не станет равным нулю. В то же время вы никогда не проверяете значение 'i', находится ли оно в пределах 'ndenoms'. Это также может привести к ошибкам вне границ, которые могут привести к неправильному завершению вашей программы.