两个用户之间的连接

时间:2013-03-12 17:06:59

标签: php mysql

我经营自己的网站,人们有能力和朋友在一起。 这就是我存储友谊的方式:

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

我们的想法是尽可能快速地找到这两者之间的联系

我能想到的唯一方法是创建一个包含大量循环的大型循环,以及可能更好,更高效的东西。

5 个答案:

答案 0 :(得分:3)

RDBMS不擅长做这样的事情。

您需要的是graph db,我强烈推荐Neo4j,这是受欢迎且开源的。

答案 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);
}

此代码经过优化以简化操作。对于除玩具数据库之外的任何东西,您应该进行双向搜索,其中保留两个列表friendedfriends(fien的树为f2)。您将扩展更短的列表,同时在另一个列表中查找匹配项。你不能欺骗复杂性,所以你必须保持对迭代的限制非常低,你喜欢垃圾服务器的声音。

答案 3 :(得分:0)

最好在两个方向上进行广度优先搜索,即从相关个人进行搜索,并在找到连接或达到指定的深度限制时停止此过程。 这个想法也是为了首先接触更受欢迎的人(同时执行BFS)

答案 4 :(得分:0)

这将是权重为1的边缘。有一个sample code来计算PHP中社交网络中2个朋友之间的连接