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 1
1 0 0 0 1
1 0 1 0 1
1 0 0 0 1
1 1 1 1 1
复制代码
邻接表表示法
邻接表是一个数组的数组,其中每个元素是一个列表,存储与节点相邻的节点。对于迷宫,每个节点都有可能有上、下、左、右四个相邻的节点。以下是相应的简化示例:
0: [1]
1: [0, 2, 3, 4]
2: [1, 4]
3: [1]
4: [1, 2]
复制代码
在这个示例中,节点 0 和节点 1 相邻,以此类推。这种方式更适合表示稀疏图,因为只存储了有边相连的节点。
你可以根据实际需求选择使用邻接矩阵或邻接表的表示方式,然后利用图搜索算法(如深度优先搜索、广度优先搜索)来解决迷宫问题。
划线
评论
复制
发布于: 刚刚阅读数: 4
鲁米
关注
生活黑客35 2019-06-11 加入
起点不重要,迭代很重要,就需要保持充分的开放和积累;而信息越充分,结果越可靠,又要求随时调整、不断逼近真相。
评论