我经营自己的网站,人们有能力和朋友在一起。 这就是我存储友谊的方式:
id1 | id2
1 | 2
1 | 3
2 | 4
基本上,用户ID 1是用户ID为2且用户ID为3的朋友,用户2为用户ID为4的朋友。
我想要的是,例如,1和4是如何连接的。目前就是这样:
1 -> 2 -> 4
如果介于4和3之间,那将是:
4 -> 2 -> 1 -> 3
我们的想法是尽可能快速地找到这两者之间的联系
我能想到的唯一方法是创建一个包含大量循环的大型循环,以及可能更好,更高效的东西。
答案 0 :(得分:3)
答案 1 :(得分:1)
通常使用称为双向搜索的算法找到最短友谊路径。主要的想法是将友谊网络视为无向图,在这里你寻找2个节点之间的最短路径。该提到的算法同时从两个节点开始搜索,发现已知节点的邻居节点。当已知节点的两个表面首先重叠时,找到最短路径。
请注意,某些特殊情况需要处理,例如当其中一个人在图中的“孤岛”时,这样的节点集没有连接到其他节点(想想没有关系的社区)外面的世界)
底线是一个不那么大的while循环。
答案 2 :(得分:1)
我首先尝试的是广度优先搜索。
请注意,以下代码无法修改,因为我甚至没有检查过语法错误。 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
(fien的树为f2)。您将扩展更短的列表,同时在另一个列表中查找匹配项。你不能欺骗复杂性,所以你必须保持对迭代的限制非常低,你喜欢垃圾服务器的声音。
答案 3 :(得分:0)
最好在两个方向上进行广度优先搜索,即从相关个人进行搜索,并在找到连接或达到指定的深度限制时停止此过程。 这个想法也是为了首先接触更受欢迎的人(同时执行BFS)
答案 4 :(得分:0)
这将是权重为1的边缘。有一个sample code来计算PHP中社交网络中2个朋友之间的连接