写点什么

31 | 深度和广度优先搜索:如何找出社交网络中的三度好友关系

作者:鲁米
  • 2023-12-12
    北京
  • 本文字数:2090 字

    阅读完需:约 7 分钟

我们通过广度优先搜索算法解决了开篇的问题,你可以思考一下,能否用深度优先搜索来解决呢?


public class WechatBFSDFS {
private final Map<Integer, List<Integer>> adjacencyList;
public WechatBFSDFS() { this.adjacencyList = new ConcurrentHashMap<>(); }
public void addEdge(int v1, int v2) { adjacencyList.computeIfAbsent(v1, k -> new ArrayList<>()).add(v2); adjacencyList.computeIfAbsent(v2, k -> new ArrayList<>()).add(v1); }
public List<Integer> getFriendsOfFriendsDFS(int start, int depth) { List<Integer> result = new ArrayList<>(); boolean[] visited = new boolean[adjacencyList.size()];
dfs(start, depth, 0, visited, result);
return result; }
private void dfs(int current, int targetDepth, int currentDepth, boolean[] visited, List<Integer> result) { if (current < 0 || current >= visited.length || visited[current] || currentDepth > targetDepth) { return; // Check for array index out of bounds or already visited } visited[current] = true; if (currentDepth <= targetDepth) { for (int neighbor : adjacencyList.getOrDefault(current, new ArrayList<>())) { dfs(neighbor, targetDepth, currentDepth + 1, visited, result); } } // Move the addition of the current node to the end result.add(current); visited[current] = false; // Backtrack }

public List<Integer> getFriendsOfFriendsBFS(int start, int depth) { List<Integer> result = new ArrayList<>(); Queue<Integer> queue = new LinkedList<>(); Set<Integer> visited = new HashSet<>();
queue.offer(start); visited.add(start);
int currentDepth = 0;
while (!queue.isEmpty() && currentDepth < depth) { int levelSize = queue.size(); for (int i = 0; i < levelSize; i++) { int current = queue.poll(); for (int neighbor : adjacencyList.getOrDefault(current, new ArrayList<>())) { if (!visited.contains(neighbor)) { queue.offer(neighbor); visited.add(neighbor); } } if(currentDepth < depth){ result.add(current); } } currentDepth++; }
return result; }

public static void main(String[] args) { WechatBFSDFS graph = new WechatBFSDFS(); graph.addEdge(1, 2); graph.addEdge(1, 3); graph.addEdge(2, 4); graph.addEdge(2, 5); graph.addEdge(3, 5);
int startNode = 1; int depth = 3;
List<Integer> friendsOfFriendsDFS = graph.getFriendsOfFriendsDFS(startNode, depth); System.out.println("Friends of friends (DFS) within " + depth + " degrees of separation from node " + startNode + ": " + friendsOfFriendsDFS);
List<Integer> friendsOfFriendsBFS = graph.getFriendsOfFriendsBFS(startNode, depth); System.out.println("Friends of friends (BFS) within " + depth + " degrees of separation from node " + startNode + ": " + friendsOfFriendsBFS); }}
复制代码


学习数据结构最难的不是理解和掌握原理,而是能灵活地将各种场景和问题抽象成对应的数据结构和算法。今天的内容中提到,迷宫可以抽象成图,走迷宫可以抽象成搜索算法,你能具体讲讲,如何将迷宫抽象成一个图吗?或者换个说法,如何在计算机中存储一个迷宫?


在计算机中,我们可以将迷宫抽象成一个图,具体而言,可以使用邻接矩阵或邻接表来存储迷宫。

邻接矩阵表示法

邻接矩阵是一个二维数组,其中的元素 a[i][j] 表示节点 i 和节点 j 之间是否有边。对于迷宫来说,我们可以使用 0 和 1 来表示通道和墙。以下是一个简化的迷宫示例:


1 1 1 1 11 0 0 0 11 0 1 0 11 0 0 0 11 1 1 1 1
复制代码

邻接表表示法

邻接表是一个数组的数组,其中每个元素是一个列表,存储与节点相邻的节点。对于迷宫,每个节点都有可能有上、下、左、右四个相邻的节点。以下是相应的简化示例:


0: [1]1: [0, 2, 3, 4]2: [1, 4]3: [1]4: [1, 2]
复制代码


在这个示例中,节点 0 和节点 1 相邻,以此类推。这种方式更适合表示稀疏图,因为只存储了有边相连的节点。


你可以根据实际需求选择使用邻接矩阵或邻接表的表示方式,然后利用图搜索算法(如深度优先搜索、广度优先搜索)来解决迷宫问题。

用户头像

鲁米

关注

生活黑客35 2019-06-11 加入

起点不重要,迭代很重要,就需要保持充分的开放和积累;而信息越充分,结果越可靠,又要求随时调整、不断逼近真相。

评论

发布
暂无评论
31 | 深度和广度优先搜索:如何找出社交网络中的三度好友关系_鲁米_InfoQ写作社区