Форум: Форум PHPФорум ApacheФорум Регулярные ВыраженияФорум MySQLHTML+CSS+JavaScriptФорум FlashРазное
Новые темы: 0000000
PHP 5/6. В подлиннике. Авторы: Кузнецов М.В., Симдянов И.В. PHP Puzzles. Авторы: Кузнецов М.В., Симдянов И.В. PHP 5. На примерах. Авторы: Кузнецов М.В., Симдянов И.В., Голышев С.В. Самоучитель PHP 5 / 6 (3 издание). Авторы: Кузнецов М.В., Симдянов И.В. MySQL 5. В подлиннике. Авторы: Кузнецов М.В., Симдянов И.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

Форум PHP

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: Рекурсия
 
 автор: demonow   (27.02.2012 в 12:21)   письмо автору
 
 


<?php
function recurs($b=10)
{
$h=0;
if(
$b==0) return;
echo 
"text<br>";
recurs($b-1);
for(
$a=0;$a<5;$a++) $h++;
echo 
$h;
}
recurs();
?>

Результат: 10 раз подряд выводит строку "text<br>", а потом 10 раз подряд выводит 5 - результат цикла.
Я уже так долго парюсь с этой рекурсией.И никак не могу понять почему именно такой результат.
Я бы понял если б оно 10 раз сначало вывело строку text а потом один раз 5, или после каждой строки text выводило бы 5, но блин почему именно так??

  Ответить  
 
 автор: Valick   (27.02.2012 в 12:34)   письмо автору
 
   для: demonow   (27.02.2012 в 12:21)
 

а так

<?php
function recurs($b)
{
$h=0;
if(
$b==0) return;
echo 
"text<br>";
for(
$a=0;$a<5;$a++) $h++;
echo 
$h;
recurs($b-1);
}

$b=10;
recurs($b);
?>

  Ответить  
 
 автор: demonow   (27.02.2012 в 12:46)   письмо автору
 
   для: Valick   (27.02.2012 в 12:34)
 

Что-то не доганяю, это тот же код только слегка изменен.
Ну вот мои размышления как оно работает:
-Обьявляется функция под именем recurs с аргументом $b
-В теле функции сначало переменной $h присваивается 0
-потом идет условие , если $b равно 0, то завершить выполнение функции(пока что у нас $b не равно 0) тобиш выполняется оператор echo
-потом идет хитрость, вызывается сама же функция но ее аргумент декрементируется а значит во вложеной функции $b уже будет 9, опят проверяется уловие и.т д.
-ну и так до самого конца пока не будет 0, а если уже 0, то выполнится return и рекурсия оборвется.
-Потом, после обрыва в теле функции ведь еще остался цикл оно его и выполняет и выводит его результат.
Но чете тут не так, мои россуждения не совпадают с результатом.
поправьте меня пож. где я россуждаю не правильно?

  Ответить  
 
 автор: cheops   (27.02.2012 в 12:51)   письмо автору
 
   для: demonow   (27.02.2012 в 12:46)
 

>поправьте меня пож. где я россуждаю не правильно?
Вы императивно рассуждаете, нужно плясать от рекурсии (поглядите картинку ниже). Вы сначала погружаетесь на 10 позиций вниз по рекурсии, потом срабатывает точка возврата b == 0 и вы начинаете подъем из рекурсии, пока не выйдете наружу. Вычислять данные можно как на спуске, так и на подъеме, иногда только на спуске вычисляют, т.е. операторы расположены ДО рекурсивного вызова, иногда на подъеме вычисляют, т.е. операторы расположены ПОСЛЕ рекурсивного вызова. У вас они расположены и на спуске и на подъеме "text" выводится на спуске, а 5 на подъеме (поглядите рисунок, который я нарисовал вам).

  Ответить  
 
 автор: demonow   (27.02.2012 в 13:49)   письмо автору
 
   для: cheops   (27.02.2012 в 12:51)
 

<?php
function recurs($b=10)
{
$h=0;
if($b==0) return;
echo "text<br>";
recurs($b-1);
for($a=0;$a<5;$a++) $h++;
echo $h;
}
recurs();
?>
А кусок кода после recurs($b-1) тоже попадает во вложеную функцию, тоесть в теле вложеной фукнции все тоже самое что и в основной?

  Ответить  
 
 автор: cheops   (27.02.2012 в 13:59)   письмо автору
 
   для: demonow   (27.02.2012 в 13:49)
 

Да, конечно. Посмотрите на рисунок и от цифр проведите горизонтальные ломтики - это и будут функции, каждая из них содержит echo "text" и каждая из них содержит echo 5. Более того каждая функция получает управление два раза, на спуске и на подъеме.

  Ответить  
 
 автор: Valick   (27.02.2012 в 12:39)   письмо автору
 
   для: demonow   (27.02.2012 в 12:21)
 

так все и должно быть
функция вызывает сама себя получается вложенность, но после вызова она не прерывается а возвращает 10 окончаний самой же себя, отсюда и пятерки в конце
___
и рекурсия оборвется
нет не оборвется, она вернется в саму себя, на уровень выше и только с самого верхнего уровня оборвется
я просто сначала не понял, что вы хотите от кода

  Ответить  
 
 автор: cheops   (27.02.2012 в 12:41)   письмо автору
29.7 Кб
 
   для: demonow   (27.02.2012 в 12:21)
 

Гляньте рисунок во вложении.

PS Рекурсия сложно понимается вами, так как она не из императивных языков. Программисты, использующие императивные языки от неё обычно в осадок выпадают :))), даже вы не удержались, чтобы цикл for добавить, точку опоры :))) хотя есть языки, где циклов вообще нет и вот этот бы for вам пришлось бы еще одной рекурсией реализовывать :)))

  Ответить  
 
 автор: demonow   (27.02.2012 в 12:53)   письмо автору
 
   для: cheops   (27.02.2012 в 12:41)
 

Спасибо, буду розбиратся.

  Ответить  
 
 автор: demonow   (27.02.2012 в 13:43)   письмо автору
 
   для: cheops   (27.02.2012 в 12:41)
 

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

  Ответить  
 
 автор: cheops   (27.02.2012 в 13:58)   письмо автору
 
   для: demonow   (27.02.2012 в 13:43)
 

Мозг, кстати, у вас все циклические задачи именно через рекурсию делает и судя по вашим вопросам прекрасно себя чувствует :))) Более того, есть языки, где нет переменных, т.е. ячеек памяти и связанных с ними именем, вернее переменные есть, но они математические, т.е. выражение вида x = x + 2 не имеет смысла, так как с точки зрения математики истинным является x = x. В таких условиях вам циклы так и так не нужны, что вы с ними будете делать, если у вас переменных нет?

Тут очень просто, вы наверное заметили, что параллельные вычисления мягко говоря набирают обороты, чипы содержат несколько ядер, видео-карты по несколько сотен параллельных обрабатывающих блоков, сеть опять же с кучей машин, которых бы надо заставить решать нужную вам задачу, а не пытаться втиснуть её в дорогущий сервер. В таких условиях именованная память становится узким местом - множеству параллельных потоков нужно около неё синхронизироваться, фактически ждать друг друга, чтобы получить доступ к телу. А если у вас нет переменных в классическом компьютерном смысле слова, то ждать нечего, знай решай задачу сотнями процессоров параллельно, а то и вообще в разных углах сети... другое дело, что составить такую программу придется на языке, который с императивным языком (C, Java, Pascal, PHP) имеет мало общего.

PS Мы сейчас примерно об этом новую книгу пишем (скажем так введение в эту область).

  Ответить  
 
 автор: demonow   (27.02.2012 в 23:35)   письмо автору
 
   для: cheops   (27.02.2012 в 13:58)
 

Вообщем помозговав немного мое представление о данном коде остановилось на такой интерпретации:
В теле функции сначало выводится echo потом обращение к функции самой на себя там тоже сначало выводится echo и т.д, но код то с циклом никуда не девается(как выяснилось выше), но так получается что он не успевает выполнится зарание, его опережает вызов функции, который выводит строку "text", и получается цикл как хвост тянется в самом конце после всех выводов текста.
Надеюсь мои мысли выражены понятно.Для меня главное понять как оно работает.

  Ответить  
 
 автор: Valick   (27.02.2012 в 23:38)   письмо автору
 
   для: demonow   (27.02.2012 в 23:35)
 

нет непонятно :)

  Ответить  
 
 автор: demonow   (27.02.2012 в 23:38)   письмо автору
 
   для: Valick   (27.02.2012 в 23:38)
 

Черт)))
Ща попробую так
-Обьявляется функция под именем recurs с аргументом $b
-В теле функции сначало переменной $h присваивается 0
-потом идет условие , если $b равно 0, то завершить выполнение функции(пока что у нас $b не равно 0) тобиш выполняется оператор echo
-потом идет хитрость, вызывается сама же функция но ее аргумент декрементируется а значит во вложеной функции $b уже будет 9, опят проверяется уловие и.т д.


<?php
function recurs($b=10)
{
$h=0;
if(
$b==0) return;
echo 
"text<br>";
recurs($b-1);
for(
$a=0;$a<5;$a++) $h++;
echo 
$h;
}
recurs();
?> 

сначало идет обращение к функции, там рекурсия, а код с циклом выполняется после, как будто цикл гонится за echo "text".
Черт, такие даунские аналогии, но мне оно почему-то так представилось.
То как рекурсия опускается я понял, но почему-то не представляется как она поднимается.

  Ответить  
 
 автор: Valick   (27.02.2012 в 23:52)   письмо автору
 
   для: demonow   (27.02.2012 в 23:38)
 

Черт)))
не я белый и пушистый :))
просто поймите каждый возврат из функции возвращается на строчку ниже вызова самой функции
а рекурсия делает с столько копий функции самой себя, сколько позволяет логика скрипта
и из последней вложенной функции возврат не может произойти в основной скрипт, возврат происходит в предыдущую копию этой функции, где и выполняется остаток функции и так до самого верха

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

  Ответить  
 
 автор: demonow   (27.02.2012 в 23:56)   письмо автору
 
   для: Valick   (27.02.2012 в 23:52)
 

но ведь, функция будет возвращатся на этаж вверх если будет выполнятся условия $b=0; так ведь, так что получается это выражения ($b=0)тянется до самого верха пока не вернет в основную программу?

  Ответить  
 
 автор: Valick   (28.02.2012 в 00:02)   письмо автору
 
   для: demonow   (27.02.2012 в 23:56)
 

угу, а с чего ему быть другим? вы ведь только отнимаете по единице

  Ответить  
 
 автор: demonow   (28.02.2012 в 00:09)   письмо автору
 
   для: Valick   (28.02.2012 в 00:02)
 

Тоесть когда $b==0, то это касается всех $b в каждой копии выше поэтому они возвращаются и выполняется цикл, так чтоль?

  Ответить  
 
 автор: Sfinks   (28.02.2012 в 00:08)   письмо автору
21.1 Кб
 
   для: demonow   (27.02.2012 в 23:38)
 

Может вам на моем рисунке понятнее будет? На нем каждый прямоугольник - это функция. Я только глубину сократил, не стал все 10 рисовать.

  Ответить  
 
 автор: demonow   (28.02.2012 в 00:15)   письмо автору
 
   для: Sfinks   (28.02.2012 в 00:08)
 

Ну да, я где-то так и думал просто проблема была с пониманием обратного хода функции.

  Ответить  
 
 автор: cheops   (28.02.2012 в 00:22)   письмо автору
 
   для: demonow   (28.02.2012 в 00:15)
 

А вы вот так код запишите. Он не вызывает затруднений? Вот рекурсия тоже самое, только функция не 10 раз повторяется, а записывается кратко.
<?php 
function recurs($b=10

  
$h=0
  if(
$b==0) return; 
  echo 
"text<br>"
  
recurs1($b-1); 
  for(
$a=0;$a<5;$a++) $h++; 
  echo 
$h

function 
recurs1($b

  
$h=0
  if(
$b==0) return; 
  echo 
"text<br>"
  
recurs2($b-1); 
  for(
$a=0;$a<5;$a++) $h++; 
  echo 
$h

...
function 
recurs8($b

  
$h=0
  if(
$b==0) return; 
  echo 
"text<br>"
  
recurs9($b-1); 
  for(
$a=0;$a<5;$a++) $h++; 
  echo 
$h

function 
recurs9($b

  
$h=0
  if(
$b==0) return; 

recurs(); 
?> 

  Ответить  
 
 автор: cheops   (28.02.2012 в 00:19)   письмо автору
 
   для: demonow   (27.02.2012 в 23:35)
 

Примерно так и есть. Посмотрите еще картинку у Sfinks, тоже хорошая. Представьте, что функция вызывает не себя, а какую-то другую функцию с другим названием - она же просто дождется когда она выполниться и пойдет выполнять оставшийся код. Тут тоже самое, только экземпляров функции 10 штук.

  Ответить  
 
 автор: demonow   (28.02.2012 в 00:25)   письмо автору
 
   для: cheops   (28.02.2012 в 00:19)
 

Все я понял, спасибо огромное всем, кто помог разобраться, это все дело было вызвано примером из книги, там рекурсивно дерево каталогов нужно вывести.Поэтому так важно четко знать смысл рекурсии.Кстате а на чем вы рисунки составляли?

  Ответить  
 
 автор: cheops   (28.02.2012 в 00:39)   письмо автору
 
   для: demonow   (28.02.2012 в 00:25)
 

>Кстате а на чем вы рисунки составляли?
Я в Visio.

  Ответить  
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования