![]() |
|
Модераторы: ginnie, korob2001 |
![]()
|
|
| aksined |
|
|||
![]() Шустрый ![]() Профиль Группа: Участник Сообщений: 58 Регистрация: 26.12.2005 Репутация: 1 Всего: 1 |
Рекурсивные алгоритмы и замена их линейными
И все-таки. Хотя пишу и уже понимаю, что накладные расходы на ведение массива и сохранение в стеке данных несколько раззличаются. А не может такого быть, что сохранять нужно не текстовую строку, а более накрученную структуру, что будет сопоставимо с рекурсией |
|||
|
||||
| sergejzr |
|
|||
![]() Un salsero Профиль Группа: Админ Сообщений: 13285 Регистрация: 10.2.2004 Где: Германия г .Ганновер Репутация: 1 Всего: 360 |
рекурсия - тот же стэк. Интерпретатор однако не знает, какие данные релевантны и поэтому сохраняет в своём стэке просто абсолютно все переменные в функции, кроме того ещё и точку выполнения, чтобы знать, откуда продолжить работу. Кроме того выполняется ещё много проверок и, возможно системных запросов. То есть при наличии сложной структуры, при рекурсии она копируется столько раз, сколько вызовов функции произошло и впамяти держаться все копии из ещё необработанных функций. Создание собственного стека - значительно упрощает ситуацию. Туда мы сохраняем только то, что действительно надо. Происходит заначительная разгрузка системы. В стек мы можем класть ссылки, а не сами обьекты, при этом обходя множество ненужных копирований, неизбежных при рекурсии. Ещё одно преимущество - управление порядком вызовов на низком уровне. То есть например заменив очередь на стек мы можем прошагать по дереву в длинну, иначе - в ширину. |
|||
|
||||
| sharq |
|
|||
![]() Perl Liker ![]() ![]() Профиль Группа: Участник Сообщений: 841 Регистрация: 13.12.2004 Где: Ростов-на-Дону Репутация: 3 Всего: 28 |
Рекурсия и линейные алгоритмы? ВОт в чем вопрос!
Все зависит от задачи, например, обход дерева с неизвестной степенью вложенности, однозначно следует делать через рекурсию. -------------------- [color=gray]There's More Than One Way To Do It[/color] |
|||
|
||||
| sergejzr |
|
|||
![]() Un salsero Профиль Группа: Админ Сообщений: 13285 Регистрация: 10.2.2004 Где: Германия г .Ганновер Репутация: 1 Всего: 360 |
Не верно. Во всяком случаи подобные утверждения следует делать с доказательствами. А я пока не вижк, почему это должно быть так. |
|||
|
||||
| sharq |
|
||||
![]() Perl Liker ![]() ![]() Профиль Группа: Участник Сообщений: 841 Регистрация: 13.12.2004 Где: Ростов-на-Дону Репутация: 3 Всего: 28 |
sergej.z как ты с помощью циклов сделаешь обход большого дерева, у которого ветки совершенно разные и разная степень вложенности?
Проще всего и лучше всего это сделать через рекурсию. ВОт пример:
А вот и обход:
Также есть задачи, для решения которых рекурсия не приминима. Вопрос: рекурсия или линейность - это вопрос не одного perl'а, а всех ЯП, которые поддерживают рекурсию. Это сообщение отредактировал(а) sharq - 28.12.2005, 18:22 -------------------- [color=gray]There's More Than One Way To Do It[/color] |
||||
|
|||||
| sergejzr |
|
||||||
![]() Un salsero Профиль Группа: Админ Сообщений: 13285 Регистрация: 10.2.2004 Где: Германия г .Ганновер Репутация: 1 Всего: 360 |
Угу, я вот перла не знаю, поэтому написал на псевдоязыке |
||||||
|
|||||||
| aksined |
|
|||
![]() Шустрый ![]() Профиль Группа: Участник Сообщений: 58 Регистрация: 26.12.2005 Репутация: 1 Всего: 1 |
sharq
А не удобнее пользоваться File::Find разве не удобнее? Кстати, сейчас смотрю, как они там реализовали обход дерева. Не факт, что используют рекурсию.Их функция справляется с гораздо более злой вложенностью, чем ты привел. Пока правда не очень получается. Очень уж там все накручено. Слушай, а что делает
С grep у меня самые большые нелады. Понимаю, что вызвал readdir в списковом контексте, отсортировал, а вот что делает grep - не пойму. Я бы делал через -d $qwe. Это сообщение отредактировал(а) aksined - 28.12.2005, 18:38 |
|||
|
||||
| sharq |
|
|||
![]() Perl Liker ![]() ![]() Профиль Группа: Участник Сообщений: 841 Регистрация: 13.12.2004 Где: Ростов-на-Дону Репутация: 3 Всего: 28 |
sergej.z рекурсия реализована с помощью стека, сделай тоже самое без стека.
-------------------- [color=gray]There's More Than One Way To Do It[/color] |
|||
|
||||
| sergejzr |
|
|||
![]() Un salsero Профиль Группа: Админ Сообщений: 13285 Регистрация: 10.2.2004 Где: Германия г .Ганновер Репутация: 1 Всего: 360 |
Зачем? рекурсия подразумевает вызов самой функции. Мой пример - линейный алгоритм, а не рекурсивный. Это стандартное решение для перевода из рекурсивный в линейное. Смысла переделывать не вижу. |
|||
|
||||
| sharq |
|
||||
![]() Perl Liker ![]() ![]() Профиль Группа: Участник Сообщений: 841 Регистрация: 13.12.2004 Где: Ростов-на-Дону Репутация: 3 Всего: 28 |
aksined
именно поэтому я написал сам.
рекурсия с любой! Добавлено @ 18:51 sergej.z ради интереса, сравню оба подхода по времени выполнения. -------------------- [color=gray]There's More Than One Way To Do It[/color] |
||||
|
|||||
| aksined |
|
||||||
![]() Шустрый ![]() Профиль Группа: Участник Сообщений: 58 Регистрация: 26.12.2005 Репутация: 1 Всего: 1 |
sharq
рекурсия и стек - не одно и то же. Вместо стека можно использовать список или какую угодно структуру хранения данных. В статье, откуда растут ноги, используется массив (хотя и используется c методами push и рор). Хотя, есть подозрение, что массивы в перл - это не массивы, а списки.
Накручено в реализации, а в использовании все просто:
придется все-таки посмотреть модуль. Думаю, что они без рекурсии сделали |
||||||
|
|||||||
| sergejzr |
|
||||
![]() Un salsero Профиль Группа: Админ Сообщений: 13285 Регистрация: 10.2.2004 Где: Германия г .Ганновер Репутация: 1 Всего: 360 |
Ассоциативные hash - массивы. Они достаточно быстры. Его можно заставить работать и как стек, и как очередь.
Ага, сравни, только на чём нибудь очень большом. А то если просто вызвать функцию много раз, только время на вызов и подсчитаешь... |
||||
|
|||||
| aksined |
|
||||
![]() Шустрый ![]() Профиль Группа: Участник Сообщений: 58 Регистрация: 26.12.2005 Репутация: 1 Всего: 1 |
так и не ответил Как говорится в тему
by Стиль написания кода на Perl Это сообщение отредактировал(а) aksined - 28.12.2005, 20:10 |
||||
|
|||||
| korob2001 |
|
||||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 2871 Регистрация: 29.12.2002 Репутация: 6 Всего: 61 |
Создаёт цикл, по отсортированному списку, который состоит из всех файлов и каталогов, которые расположены в каталоге $dir и которые не содержат точки в своём имени.
В перл ещё есть такое понятие, как побочный эффект. Это когда ты вызываешь какую либо функцию не для того, что бы получить то, что она возвращает, а для того, что бы получить то, что она делает. Потому вовсе не обязательно, создавать foreach когда у тебя в теле всего одно или 2 действия и тебе их нужно выполнить на каждой итерации по списку, в данном случае map работает быстрее. Хотя данное утверждение не относится к коду выше, потому как это не void конетекст. foreach не явно создаёт список элементов в памяти, а grep его возвращает. Потому, получается примерно следующее. 1. readdir $dir - возвращает список файлов и каталогов из каталога $dir. 2. Затем список передаётся в sort, что не есть гуд. Получается мы сортируем список до того, как часть его будет отброшена grep, на следующем шаге. Но над этим ещё нужно подумать. 3. sort передаёт отсортированный список в grep, который отбрасывает файлы или каталоги, содержащие в своих именах точки. 4. foreach получает список и создаёт его не явно в памяти и выполняет проход по этому списку. Тепрь можно вернуться к к сортировке. Если я не ошибаюсь то sort работает гораздо медленее grep, быть может лучше попробовать сначала отбрасывать все файлы с точками в именах, а после передавать этот список в sort? С другой стороны, в grep используется не совсем удачный шаблон, который будет проверять каждый символ, каждого элемента списка. Нужно потестировать. Это сообщение отредактировал(а) korob2001 - 28.12.2005, 21:18 -------------------- "Время проходит", - привыкли говорить вы по неверному пониманию. "Время стоит - проходите вы". |
||||
|
|||||
| sharq |
|
||||||||||||||
![]() Perl Liker ![]() ![]() Профиль Группа: Участник Сообщений: 841 Регистрация: 13.12.2004 Где: Ростов-на-Дону Репутация: 3 Всего: 28 |
aksined
Рекурсия использует стек. А то, что это одно и тоже я не говорил!
Стек - это всего лишь название способа доступа к данным (LIFO), а как ты будешь его реализовывать, это твое дело.
Использовать все просто, вызвал функцию и все, то, что работает, не значит, что работает так, как надо для данной задачи.
К сожалению, не в ту тему. Здесь нет явного присвоения, для того чтобы избежать создание избыточных переменных. Можно было написать так, но это работает дольше и код увеличивается на одну строку:
И никакого побочного эффекта здесь нет! О чем и сказал korob2001.
Здесь поясню, имелись в виду след. директории: "." или "..", их обрабатывать не надо, поэтому пропускаем. Хотя шаблон отбрасывает все названия, в которых есть точка. Это сообщение отредактировал(а) sharq - 29.12.2005, 00:17 -------------------- [color=gray]There's More Than One Way To Do It[/color] |
||||||||||||||
|
|||||||||||||||
![]()
|
| Правила форума "Perl: Системное программирование" | |
|
|
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, korob2001, sharq. |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | Perl: Системное программирование | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |