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 相邻,以此类推。这种方式更适合表示稀疏图,因为只存储了有边相连的节点。
你可以根据实际需求选择使用邻接矩阵或邻接表的表示方式,然后利用图搜索算法(如深度优先搜索、广度优先搜索)来解决迷宫问题。
划线
评论
复制
发布于: 刚刚阅读数: 4

鲁米
关注
生活黑客35 2019-06-11 加入
起点不重要,迭代很重要,就需要保持充分的开放和积累;而信息越充分,结果越可靠,又要求随时调整、不断逼近真相。










 
    
评论