计算社交关系人物之间的最短距离(无向图顶点之间的最短距离)

最近在写实验的过程中,遇到在社交关系网络中,计算两个人物之间的最短距离的问题,恰巧之前也写过在无向图中,计算两个顶点之间的最短距离的问题,两者是一种问题,所以在这里记录一下。

关于人物之间的关系,这里我在Person类里设置一个Set集合的Rep来当做该人物的朋友圈(对于无向图来说,这个Set集合就用来存放与之相连的所有顶点了),见代码:

public class Person {
	String name;
	Set friends = new HashSet();
	 Person(String name) {
		 this.name = name;
	}
	 /* 调取该人物的名字 */
	public String getName() {
		return this.name;
	}
}

人物对象建立完毕,就要开始进入主题了。既然是人物A到人物B的最短距离,就要涉及到广度优先搜索了,以下是我的计算思路:
(1):将人物A的朋友(朋友圈里的所有人)添加到一个待查询的队列里(只添加没有查询过的人物);

(2):从前往后遍历队列,分别对每个人物的朋友圈进行遍历,遇到未添加到队列里的人物,则添加到队列里,直到队列里的所有人物都被访问过,结束;
(2.1):将每一层添加到队列里的人数记录到一维数组中;
(2.2):在查找到目标人物的同时,记录其在队列里的下标,结束遍历;

(3):根据得到的下标,依次减去每层的人数,计算遍历的层数,计算深度(即距离)。

当人物A与人物B没有关系时,返回-1,当人物A与人物B是同一个人物时,返回0,其他情况则返回他们之间的最短距离。见代码:

/**
    * 计算两个人物之间的最短距离.
    * @param person1 人物1
    * @param person2 人物2
    * @param numbers 总人数(这个社交关系网所络涉及到的所有人)
    * @return 人物1没有朋友或者与人物2没有关系则返回-1,人物2在人物1的朋友圈里则返回1,
    *         人物1与人物2是同一个人则返回0,其他情况则返回两者之间的最短距离
   */
   
  public int getDistance(Person person1,Person person2,int numbers) {
  
  //已经被访问过的人物(不会被重新加入到待查询的人物列表list中)
    Set checked = new HashSet();
    //记录人物2在list中出现的位置下标
    int index = -1;
    /* 待查询的人物列表(初始阶段,人物1的朋友们会被加入到这个列表中,随着广度优先搜索,不断在列表后面添加未被访问过的人物)*/
    List list = new ArrayList<>();
    //存放每一层的人物数量
    int[] amount = new int[numbers + 1];
    if (person1.friends().isEmpty()) {
      return -1;
    }
    if (person1.friends().contains(person2)) {
      return 1;
    }
    int distance = 0;
    if (person1.equals(person2)) {
      return 0;
    } else {
      checked.add(person1);
      Iterator iter1 = person1.friends().iterator();
      int in = 0;	//层数,即第in + 1层
      amount[in] = person1.friends().size();
      
      //初始阶段,人物1的朋友们被加入到list列表中
      while (iter1.hasNext()) {
        Person person = iter1.next();
        checked.add(person);
        list.add(person);
      }
      int count = 0;	//记录当前层访问的人数,以每一层为一个周期,count归零
      int newPersonNumber = 0;	//在查找过程中加入到list列表里的新一层的人物数量
      int personInLevel = amount[0];	//当前层的人数,初始阶段,它的值便是人物1的朋友数量
      Person temp;	//依次从list中过去人物,赋值给temp
      Person son;	//temp的朋友,即:人物1 ——> temp ——> son
      for (int i = 0;i  < numbers && i < list.size();i++) {
        temp = list.get(i);
        count++;
        if (temp.friends().contains(person2)) {
          index = i + 1;
          break;
        } else {
          Iterator iter2 = temp.friends().iterator();
          while (iter2.hasNext()) {
            son = iter2.next();
            if (!checked.contains(son)) {
              newPersonNumber++;
              checked.add(son);
              list.add(son);
            }
          }
        }
        //当count等于当前层的人物数量,当前层查找结束,将personInLevel更新为下一层的人物数量,即
        if (count == personInLevel) {
          in = in + 1;
          amount[in] = newPersonNumber;	//将新一层的人物数量记录到amount数组中
          personInLevel = newPersonNumber;	//即将对新一层进行遍历查找,所以将当前层的人物数量进行更新
          newPersonNumber = 0;	//归零,开始新一层人物数量的计数
          count = 0;	//当前层已经访问的人物数量归零
        }
      }
      //所有查找完毕,未查找到人物2,因此人物1与人物2之间没有关系,返回-1
      if (index == -1) {
        return -1;
      }
    }
    //因为是从人物1的朋友的朋友圈开始查找的,因此起始距离为2
    distance = 2;
    for (int j = 0;j < amount.length;j++) {
      index = index - amount[j];  //减去一层的人物数量,若大于0,则深度加1,即距离加1
      if (index > 0) {
        distance++;
      }  else {
        break;
      }
    }
    return distance;
  }

至此,人物1与人物2之间的最短距离就计算出来了,无向图中两个顶点之间的最短距离也可以用这个方式去计算,即使这种方法比较笨拙和麻烦,但也不失为一种解决方式嘛~ 毕竟比起让我这种菜鸟级别的小白头昏眼花的高深巧妙的方法,这种笨拙但是易懂的方法更能让我接受哇~

你可能感兴趣的:(算法,社交关系网络,无向图)