Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 13.04.2010, 21:23   #1
vedro-compota
любитель-далеко не
Участник клуба
 
Аватар для vedro-compota
 
Регистрация: 13.04.2010
Сообщений: 1,156
Стрелка рекурсивная функция))

Уважаемые форумчане! Уже второй день решаю простенькую(с точки зрения объёма кода) задачку и решить не могу ! моя рекурсивная функция,по идее, должна считать число вхождений элемента "b" в список. Я передаю в функцию указатель на последний элемент списка. Список состоит из записей ( type record) одно из полей информационное( у меня это integer) а другое-содержит указатель на предыдущий элемент. что-то не так , выполнял пошагово- так там ужас какой-то при исполнии компилятор(строка просто выделенная- не знаю как назвать)) заходит в функцию уже после того, как r=nil. не знаю что и думать. о- это просто глобальная переменная(пытался использовать чтобы сравнить результат с результатом ,который возвращает функция- но толку от этого мало) помогите, пожалуйста ))
вот она, эта функция -
Код Delphi


Код:
function fg ( r: pelement ; b:integer):integer; //рекурсивная функция
begin
  if (r=nil)  then  fg:=0;  // условие выхода из рекурсии ( результат преобретает конкретное значение)
  if (r<>nil) and (b=r^.infa) then
  begin
    o:=o+1;
    r:=r^.ukazatel;
    fg:=1+fg(r,b);
  end;
  if (r<>nil) and (b<>r^.infa) then  // если значение очередного элемента списка не совпадает
  begin                             // с заданным значением b то просто вызываем функцию ещё раз.
    r:=r^.ukazatel;
    fg:=fg(r,b);
  end;
 
end;
если нужно могу выложить код всей программы- она небольшая))
против абортов=за + жизнь;.фкн вгу;_______________________мойблг
vedro-compota вне форума Ответить с цитированием
Старый 13.04.2010, 21:50   #2
vedro-compota
любитель-далеко не
Участник клуба
 
Аватар для vedro-compota
 
Регистрация: 13.04.2010
Сообщений: 1,156
По умолчанию

Код:
procedure TForm1.Button2Click(Sender: TObject);
var zap: telement;
    p:pelement;
    uk: pelement;
    i,n,ot,b  : integer;
begin
  ot:=0;
  o:=0;
  z:=0;
  label5.Caption:='';
  label3.Caption:='';
  n:=0;
  uk:=nil;
  while n<=stringgrid1.colcount-1 do // формирую список
  begin
    if length(stringgrid1.Cells[n,0])<>0 then
    begin
      new(p);
      p^.ukazatel:=uk;
      uk:=p;
      p^.infa:=strtoint(stringgrid1.cells[n,0]);
      n:=n+1;
    end
    else
    n:=n+1;
  end;
  b:=strtoint(edit2.text);  // узнаю какой элемент меня интересует
  ot:=fg(uk, b);
  label3.Caption:=inttostr(ot); // ответ ( вывожу на форму)
против абортов=за + жизнь;.фкн вгу;_______________________мойблг
vedro-compota вне форума Ответить с цитированием
Старый 13.04.2010, 22:38   #3
Serge_Bliznykov
Старожил
 
Регистрация: 09.01.2008
Сообщений: 26,229
По умолчанию

абсолютно не думая, просто "пальцем в небо"...

а разве при r=nil не надо из процедуры выходить?
вот так:
Код:
function fg ( r: pelement ; b:integer):integer; //рекурсивная функция
begin
    // условие выхода из рекурсии ( результат преобретает конкретное значение)
  if (r=nil)  then  begin fg:=0; Exit end;  
 ....
Serge_Bliznykov вне форума Ответить с цитированием
Старый 14.04.2010, 10:03   #4
vedro-compota
любитель-далеко не
Участник клуба
 
Аватар для vedro-compota
 
Регистрация: 13.04.2010
Сообщений: 1,156
Хорошо

прям так и пишется? )) после "exit" не надо точку с запятой? хотя, сейчас попробую.)) спасибо за ответ))
-------------------------------------------------------------------------------------------------------
попробовал сделать как вы посоветовали, но ничего не изменилось )) для трёх элементов список (1, 2, 3) моя функция при запросе для b=2 выдаёт ответ "fg=0" , а глобальная переменная "о=1" ( для глобальной переменной результат, получается, правильный)
(дело в том, что я очередной элемент я добавляю в начало списка- потому функция перебирает значения в последовательности 3 - 2 - 1 )
не пойму в чём ошибка. да и из рекурсии выход выполняется, как только функция не вызывается ещё раз :
Код:
if (r=nil)  then  fg:=0;
а во всех остальных случаях ( когда ещё есть с чем сравнивать) функция вызывает сама себя.......вот так, если элемент в списке оказался равным элементу "b" :
Код:
fg:=1+fg(r,b);
и вот так , если эти элементы (целые числа) различны:
Код:
 fg:=fg(r,b);
то есть просто вызываю функцию ещё раз (не наращивая значение). вот такие у меня рассуждения по поводу реализации функции. в чём же ошибка?
против абортов=за + жизнь;.фкн вгу;_______________________мойблг

Последний раз редактировалось vedro-compota; 14.04.2010 в 11:18.
vedro-compota вне форума Ответить с цитированием
Старый 14.04.2010, 18:37   #5
vedro-compota
любитель-далеко не
Участник клуба
 
Аватар для vedro-compota
 
Регистрация: 13.04.2010
Сообщений: 1,156
Восклицание

Serge_Bliznykov, на тебя вся надежда. на 3-ёх форумах на мою просьбу отклинулся только ты.......можно на ты?
(товарищи модераторы не баньте меня за второе подряд сообщение- я и так предыдущее три раза редактировал)))
-----------------------------------------------------------------------------------
не дождался вашего ответа сегодня- дождусь завтра))
против абортов=за + жизнь;.фкн вгу;_______________________мойблг

Последний раз редактировалось vedro-compota; 15.04.2010 в 01:18.
vedro-compota вне форума Ответить с цитированием
Старый 15.04.2010, 09:57   #6
Serge_Bliznykov
Старожил
 
Регистрация: 09.01.2008
Сообщений: 26,229
По умолчанию

и на будущее, при наличии исходного кода, помочь намного легче!!!______________________

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

и ещё. я чуть подшаманил логику...
НО! У Вас БОЛЬШАЯ ошибка в логике работы со списком! Список создали и заполнили.
А кто его удалять/освобождать память будет?! Пушкин?!
(я код удаления не писал. возьмите по поиску, тут на форуме полно примеров работы с односвязным списком)
Вложения
Тип файла: rar f2_Sources_Only.rar (1.9 Кб, 6 просмотров)
Тип файла: rar f2_Sources_with_Exe.rar (156.7 Кб, 6 просмотров)

Последний раз редактировалось Serge_Bliznykov; 15.04.2010 в 10:49.
Serge_Bliznykov вне форума Ответить с цитированием
Старый 15.04.2010, 10:51   #7
vedro-compota
любитель-далеко не
Участник клуба
 
Аватар для vedro-compota
 
Регистрация: 13.04.2010
Сообщений: 1,156
Хорошо вас понял)

буду делать, как вы сказали ) мне вот буквально час назад задачу эту объяснили ), если кому интересно:
ошибка была в том, что два последние условия(if) не были полностью независимы друг от друга . в результате если элемент обнаруживался в списке ,выполнялась последовательность команд:
Код:
r:=r^.ukazatel;
fg=1+fg(r,b);
далее (если следующий элемент списка не равен заданному) значение функции просто "затирается" так как следующее условие (b<>r^.infa) оказывается верным, то есть вместо fg=1+fg(r,b); (что было нужно) мы получаем: fg=fg(r,b); (что не верно)
соответственно мы должны исключить возможность одновременного выполнения
Код:
r:=r^.ukazatel;
Код:
fg:=1+fg(r,b);
и
Код:
r:=r^.ukazatel;
    fg:=fg(r,b);
этого можно достигнуть переписав функцию в виде) :
f
Код:
unction fg ( r: pelement ; b:integer):integer; //рекурсивная функция
begin
  if (r=nil)  then begin Result:=0; end;  // условие выхода из рекурсии ( результат преобретает конкретное значение)
  if (r<>nil) and (b=r^.infa) then
  begin
    o:=o+1;
    Result:=1+fg(r^.ukazatel,b);
  end;
  if (r<>nil) and (b<>r^.infa) then  // если значение очередного элемента списка не совпадает
  begin
    Result:=fg(r^.ukazatel,b);
  end;

end;
----------------------------------------------------
Спасибо , Serge_Bliznykov'у ) буду следовать его советам)
против абортов=за + жизнь;.фкн вгу;_______________________мойблг
vedro-compota вне форума Ответить с цитированием
Старый 15.04.2010, 13:25   #8
Serge_Bliznykov
Старожил
 
Регистрация: 09.01.2008
Сообщений: 26,229
По умолчанию

1) выкинь глобальную переменную o
2) я же предложил чуть другой вариант (был во вложении).
Объедив идеи, получаем код:
Код:
function fg ( r: pelement ; b:integer):integer; //рекурсивная функция
begin
  // условие выхода из рекурсии ( результат преобретает конкретное 
  значение)
  if (r=nil)  then fg:=0   
  else  //f (r<>nil) 
    begin
     if (b=r^.infa) then 
        fg:=1+fg(r^.ukazatel,b)
     else 
          // если значение очередного элемента списка не совпадает
          // с заданным значением b то просто вызываем функцию ещё раз.
        fg:=fg(r^.ukazatel,b);
    end;
end;

Последний раз редактировалось Serge_Bliznykov; 15.04.2010 в 13:30.
Serge_Bliznykov вне форума Ответить с цитированием
Старый 16.04.2010, 14:39   #9
vedro-compota
любитель-далеко не
Участник клуба
 
Аватар для vedro-compota
 
Регистрация: 13.04.2010
Сообщений: 1,156
Стрелка

глобальная переменная была для контроля над бесконтрольной функцией)) (хотя и не помогала).

Да, вы правы, так ещё красивее, спасибо))
против абортов=за + жизнь;.фкн вгу;_______________________мойблг
vedro-compota вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
C++ Рекурсивная функция Trinity13 Помощь студентам 10 15.10.2017 13:21
Рекурсивная функция Skinnyman Помощь студентам 4 16.03.2010 18:05
Рекурсивная функция Trinity13 Помощь студентам 8 14.02.2010 18:44
Си++. Рекурсивная функция. Diamond2107 Помощь студентам 6 02.12.2009 19:48