kyrenesjtv.github.io

https://kyrenesjtv.github.io/


Project maintained by kyrenesjtv Hosted on GitHub Pages — Theme by mattgraham

跟书单广度优先搜索条件一样,只不错双向广度搜索,从两个节点触发。

 /**
     * 双向广度查找两个用户之间的广度距离
     * @param user_nodes 好友关系网
     * @param user_id_a 用户a的ID
     * @param user_id_b 用户b的ID
     * @return 用户a b 的广度距离  -1表示超出距离或者没有找到,0表示a和b是相同用户
     */
    public static int bi_bfs(Node[] user_nodes , int user_id_a , int user_id_b){

        //用户id超出关系网长度
        if(user_id_a > user_nodes.length || user_id_b>user_nodes.length){
            return -1;
        }
        //用户相同
        if(user_id_a == user_id_b){
            return 0;
        }

        //队列a
        LinkedList<Integer> quene_a = new LinkedList<>();
        //队列b
        LinkedList<Integer> quene_b = new LinkedList<>();

        //a放入队列
        quene_a.offer(user_id_a);
        //a 访问过的人
        HashSet<Integer> set_a = new HashSet<>();
        set_a.add(user_id_a);

        //b放入队列
        quene_b.offer(user_id_b);
        //b 访问过的人
        HashSet<Integer> set_b = new HashSet<>();
        set_b.add(user_id_b);

        //max_degree 防止死循环
        int degree_a = 0 ,degree_b = 0 ,max_degree =20;

        while((degree_a +degree_b) <max_degree){
            degree_a++;
            //沿着a的方向,继续广度朝赵degree +1 的好友
            getNextDegreeeFriend(user_id_a,user_nodes,quene_a,set_a,degree_a);
            //判断是否有交集
            if(hasOverlap(set_a,set_b)){
                return degree_a +degree_b;
            }

            degree_b++;
            //沿着a的方向,继续广度朝赵degree +1 的好友
            getNextDegreeeFriend(user_id_b,user_nodes,quene_b,set_b,degree_b);
            //判断是否有交集
            if(hasOverlap(set_a,set_b)){
                return degree_a +degree_b;
            }
        }
        return  -1 ;
    }

    /**
     *  判断2个hashSet是否有交集
     * @param set_a
     * @param set_b
     * @return true有交集, false没有
     */
    private static boolean hasOverlap(HashSet<Integer> set_a, HashSet<Integer> set_b) {

        if(set_a.isEmpty() || set_b.isEmpty()){
            return false;
        }

        for (Integer num : set_a){
            if(set_b.contains(num)){
                return true;
            }
        }
        return false;
    }

    /**
     *  找到当前用户的下一度好友
     * @param user_id_a 当前用户的id
     * @param user_nodes 人际关系网
     * @param quene_a 队列,将要被查找的人的id
     * @param set_a 已被探测到跟a有关系的人
     * @param degree_a 几度好友
     */
    private static void getNextDegreeeFriend(int user_id_a, Node[] user_nodes, LinkedList<Integer> quene_a, HashSet<Integer> set_a, int degree_a) {
        if(user_nodes[user_id_a] == null){
            return;
        }

        Node current_node = user_nodes[user_id_a];
        //获取到当前用户的好友
        HashSet<Integer> friends = current_node.friends;
        if(friends.isEmpty()){
            return;
        }
        HashMap<Integer, Integer> degrees = current_node.degrees;
        //填充数据
        for(Integer frindID : friends){
            quene_a.offer(frindID);
            set_a.add(frindID);
            degrees.put(frindID,degree_a);
        }

    }

但是双向广度有某一些问题

  1. oom问题:若2者之间没有联系关系呢?
  2. 效率问题:若a有100个共同好友,b有2个共同好友,那么双向必定比单向效率高吗?