我首先要尝试的是广度优先搜索。
请注意,如果不进行修改,以下代码将无法运行,因为我什至没有检查语法错误。如您所见,query() 函数应返回条目列表。它的目的是给你一个想法。
/* Return one of the shortest friendship paths from f1 to f2. Returns false when
* path is longer than limit or no path exists.
* PROTOTYPE FIX IT YOURSELF
*/
function friend_path($f1, $f2, $limit) {
$friended = array($f1 => false); // The tree of friendships leading to f1
$discovered_friends = array($f1); // List of friends to examine next
while($limit-- > 0) {
$interesting_friends = $discovered_friends;
$discovered_friends = array();
foreach(query("
SELECT id1 AS friender, id2 AS friendee
FROM friendships
WHERE id1 in (".join(',', $interesting_friends).")
") as $discovered_link
) {
$friendee = $discovered_link['friendee'];
$friender = $discovered_link['friender'];
if (!isset($friended[$friendee])) {
$discovered_friends []= $friendee;
$friended[$friendee] = $friender;
if ($friendee == $f2) {
return friend_path_track($friended, $friendee, $track);
}
}
}
if (count($discovered_friends) < 1) return false;
}
return false;
}
function friend_path_track($friended, $friendee, $track) {
$track []= $friendee;
if ($friended[$friendee]) === false) return array_reverse($track);
return friend_path_track($friended, $friended[$friendee], $track);
}
为简单起见,此代码进行了优化。对于除了玩具数据库之外的任何东西,您应该进行双向搜索,其中保留两个列表friended
和friends
(f2 的好友树)。您将扩展较短的列表,同时在另一个列表中寻找匹配项。但是,您无法欺骗复杂性,因此您必须将迭代限制保持在非常低的水平,除非您喜欢破坏服务器的声音。