Доброго времени суток. На просторах интернета нашел такую вот задачку: Есть пункты, с расстояниями и временем пути между ними. Нужно при выборе двух точек отобразить расстояние и время. Если прямого соединения нету - нужно подобрать оптимальный маршрут (на этом и завис). Схематически это выглядит так: Таблица выглядит так (дамп здесь). Под список точек завел отдельную таблицу, айдишники которых ниже: Код (PHP): id cities_id_1 cities_id_2 distance_km time_mins 1 1 2 80 40 2 1 3 110 55 3 1 5 330 240 4 3 4 60 20 5 3 5 205 80 6 5 6 80 40 7 2 6 340 230 8 4 6 192 110 Идея была такой: на вход подаю нужную точку, при помощи рекурсивной функции построить многомерный массив, который будет строиться, пока не будет достигнута конечная точка. В итоге получаю массив Код (PHP): $tree[1][3][4][6] , который перебираю и получаю маршрут. На момент написания сего поста, функция виглядит так: Код (PHP): <?php $db = new PDO('mysql:host=localhost;dbname=task', 'root', ''); $city_id = 1; function getTree($id){ global $db; $tree = array(); $query = "(SELECT cities_id_1 FROM distance_time WHERE cities_id_2=$id) UNION (SELECT cities_id_2 FROM distance_time WHERE cities_id_1=$id)"; $st = $db->query($query); $res = $st->fetchAll(PDO::FETCH_ASSOC); foreach($res as $k => $v){ if(is_array($v)){ foreach($v as $p){ $tree[$p] = getTree($p); if($v == $p) continue; } } } return $tree; } echo "<pre>"; print_r(getTree($city_id)); echo "</pre>"; ?> Чем я прошу Вас помочь: 1. На верном ли я пути? Если есть другие пути решения, прошу подсказать какие, но так же прошу помочь в решении этим способом. 2. С моей точки зрения пока функция написана верно, но страница падает, так и не загрузившись. Как заставить ЭТОТ код заставить сгенерировать хотя бы нужный мне массив. Пока не ставил запрос с объединением, а просто выбором с одного поля, все было нормально, работало как я и хотел. 3. В случае получения нужного мне массива, я пока не представляю как использовать вложеность ключей, что бы их потом обработать и вывести нужный результат. ЗЫ. Я ОЧЕНЬ начинающий в этом деле, так что прошу сильно не ругать). PHP, JavaScript, SQL и другой код пишите внутри тегов Код ( (Unknown Language)): [b]php][/b]Тут код[b][/[/b][b]code][/b][/color]
За советы, конечно, спасибо, но хотелось бы услышать мнение специалистов. Что стобственно не так? Почему рекурсивная функция не работает так, как надо?
На вскидку: 1) Тупо вычерпываешь лимит стека вызовов. 2) Вычерпываешь лимит памяти. 3) Вычерпываешь лимит времени. 4) Накосячил с выходом из рекурсии и вводимый граф скидывает твой код в вечность. В чем ты кодишь? Отладчик прицеплен? Пошагово можешь продебажить?
Был приятно удивлен, когда прочел об этом алгоритме. Оказывется, я хоть и не был незнаком с ним, но так и спланировал логику приложения. Добавлено спустя 1 минуту 7 секунд: Дружище, я пока ОЧЕНЬ начинающий в этом деле. Если тебе не сложно, объясни пожалуйста на "пальцах". А я пока погуглю все то, что ты написал)
treez отладка (debug) это просто спаситель, ты можешь проследить как работает каждая строчка кода и какие данные содержит. Вручную http://phpfaq.ru/debug Через IDE https://netbeans.org/kb/docs/php/debugging_ru.html + например open-server.ru Online IDE c9.io
Окай. Стек - это такой накопитель, суть которого в том, что элемент, который был последним туда помещен, должен быть первым оттуда изъят. Как стопка тарелок. Кладем одну на одну и, в момент времени, у нас доступна только верхняя. Это называется LIFO - Last In, First Out. Когда ты вызываешь какую-то функцию, ты передаешь управление из одного кода в другой. А потом возвращаешь его обратно. Программе как-то надо отслеживать все эти прыжки и переходы, верно? И есть у нее такая вещь, как "стек вызовов". Это такой системный стек, куда складываются все вызовы функций в твоем коде. Когда ты вызываешь функцию, туда кладется запись. Когда функция завершается, самая последняя запись изымается, управление передается коду, который связан с записью, которая лежала под ныне изъятой. Вызвал ты функцию А из функции Б из функции В, получил стопочку из трех тарелочек (в каждой тарелочке, между прочим лежит в заблокированном состоянии вся занятая ранее память, запомни этот момент). В отработала, управление вернулось в тарелочку Б. Б отработала, управление вернулось в тарелочку А. Беда в том, что максимальная высота этой стопки тарелок не неограниченная. Потолок, в который она упирается, таки существует. Суть рекурсии в том, что ты, за N проходов складываешь в стопку N тарелок. Если это N ниже, чем наш потолок, то, в конце, все тарелочки будут убраны в обратном порядке. Если N выше, чем наш потолок - упс... Помнишь, я говорил, о том, что тарелочки не пустые? Дело в том, что количество памяти, которое разрешено скушать PHP за одну отработку ограничено. Оно правится в конфигах, разумеется, но ограничено. И по умолчанию не велико. Если твои тарелочки довольно увесисты, скрипт может попросту упереться в это ограничение и умереть - стол не выдержал стопку. Аналогично проблеме с памятью. В конфигах указано время, которое отводится на обработку запроса. Когда оно заканчивается, работа скрипта обрывается, закончил он ее или нет. Не успел сложить и разобрать тарелочки вовремя - твои проблемы. А это самое веселое - ты сказал, как надо складывать тарелочки, но не объяснил точно, когда надо прекратить этот процесс. То есть, если в предыдущих случаях процесс складывания конечен, но долог или ресурсоемок, в данном же варианте не помогут правки конфига. Править надо сам алгоритм. От себя еще добавлю, что 1) Включи вывод ошибок. 2) Найди, где у тебя лежат логи пхп и почитай их, мб чего интересного найдешь. 3) Прислушайся к Денису по части отладки.