Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Vtoraya_chast_uchebnika_po_WWW_Okonchat_variant...doc
Скачиваний:
31
Добавлен:
27.09.2019
Размер:
6.06 Mб
Скачать

Пример 4‑23

<?php

//Задание (определение) итеративной функции

function reverse_i($stroka) //Начало итеративной функции

{

$dlinaStroki = strlen($stroka);

// $obrStroka= ""; //Очистка результирующей строки

for ($i=1; $i<=$dlinaStroki; $i=$i+1)

// Следующая строчка - конкатенация очередного символа к результату

$obrStroka=$obrStroka.substr($stroka, -$i,1);

return $obrStroka;

} //конец итеративной функции

//------------------------------------------------------

//Задание исходной строки для обращения

$ishodnStroka = 'кот';

echo "Исходная строка для обращения: $ishodnStroka <br>";

//Проверка работы итеративной функции

echo "Результат обращения исходной строки с использованием итеративной функции: ";

//Вызов итеративной функции и вывод результата её работы

echo reverse_i($ishodnStroka),"<br>";

//------------------------------------------------

//Определение рекурсивной функции

function reverse_r($stroka) //Начало рекурсивной функции

{

$dlinaStroki = strlen($stroka);

if ($dlinaStroki>0) // условие окончания рекурсии

{

$obrStroka=reverse_r (substr ($stroka,1)).substr($stroka,0,1);

}

return $obrStroka;

} //Конец рекурсивной функции

//Проверка работы рекурсивной функции

echo "Результат обращения исходной строки с использованием рекурсивной функции: ";

//Вызов рекурсивной функции и вывод результата её работы

echo reverse_r($ishodnStroka);

?>

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

В этом листинге реализованы две функции. Обе будут выводить строку в обратном порядке. Функция reverse_r() — рекурсивная, a reverse_i() — итеративная.

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

reverse_r('от');

reverse_r('т');

reverse_r('');

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

При каждом вызове проверяется длина переданной строки. По достижении конца строки условие оказывается ложным (strlen()==0). После этого последний экземпляр функции (reverse_r('')) будет завершен и будет выполнена следующая строка кода, повторяющая на экране первый символ переданной строки — в данном случае никакой, поскольку строка пуста.

Затем этот экземпляр функции возвращает управление экземпляру, который вызвал его, а именно — reverse_r("т"). Этот экземпляр выводит первый символ – в своей строке, 'т', и возвращает управление вызвавшему его экземпляру.

Этот процесс — вывод символа и возврат к экземпляру функции, расположенному над ним в порядке вызова — продолжается до тех пор, пока управление не будет возвращено основной программе.

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

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

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