Social Network
问题说明
在这个问题中,我们需要设计两个类。实现并测试一个FriendshipGraph类,该类表示社交网络中的友谊,并且可以计算图中两个人之间的距离。还需要实现一个辅助类Person。同时应该将社交网络建模为一个无向图,其中每个人都连接到零个或多个人,但是底层图的实现应该是有向的。但是这个问题拟刻画的社交网络是无向图,但你的类设计要能够支持未来扩展到有向图。正因为此,如果要在两个Person对象A和B之间增加一条社交关系,那么需要同时调用addEdge(A,B)和addEdge(B,A)两个语句。同时需要能够在图像中添加顶点和边。getDistance方法应将两个人作为参数,并返回人与人之间的最短距离(整数);如果两个人没有连接(或者没有任何路径可以到达),则返回-1。
设计Person类
在Person类的设计过程中,因为是要辅助FriendshipGraph类的完成,因此我们设计了相关的一些属性和几个得到属性内容的方法如下:
private String personname;
public boolean visit;
private List<Person> friends;
其中personname是用来保存人名的,visit是用来标记是否进行过访问的,friends是用来保存朋友列表的。相关的几个方法如下,都是为了辅助FriendshipGraph类完成而设计的:
public void addtoFriends(Person a){
this.friends.add(a);
}
public String getName() {
return this.personname;
}
public List<Person> getFriends(){
return this.friends;
}
设计FriendshipGraph
在这个类的设计和实现中,首先我们需要定义一个动态数组保存所有的人,同时还需要一个集合用来保存所有人的名字,这个集合可以用来判断重名,同时进行错误提示信息。
在addVertex方法中,我们需要判断重名,如果名字出现了重复,那么就应该退出程序,如果是独立的名字,那么就应该添加到人的数组中,名字也要添加到对应的集合中。
在addEdge方法中,我们只需要在输入参数中将后面的参数Person b加入到Person a的朋友列表中。同时在此处需要注意对输入参数的判断,判断a和b是否为同一个人,以及a、b是否已经添加入人的数组中了,同时,还需要判断是否发生了重复的边,这里存在一个错误信息的处理,具体代码如下:
if((!personsname.contains(a.getName()))||(!personsname.contains(b.getName()))||(a.getName() == b.getName())) {
return false;
}
for(int i = 0;i < a.getFriends().size();i++) {
if(b.getName() == a.getFriends().get(i).getName()) {
return false;
}
}
a.addtoFriends(b);
return true;
在这个类的设计中,最主要的要实现的方法就是getDistance方法。这个方法要求返回输入两个人之间的最短距离。需要注意如果输入是同一个人,那么我们需要返回0。在这里采用的是广度优先搜索的策略。对输入的第一个参数,先将他标记为访问过,然后将这个人加入到队列中,同时保存距离。下面进入循环判断,取出队首元素,然后依次遍历a的朋友,如果没有访问过则将其纳入队列中,同时这个距离加1。一直判断到在朋友列表中遇到了第二个参数b,在这个时候返回对应的距离。如果这个时候队列为空,且并未返回,那么说明a无法到达b,返回-1。关键的判断代码如下:
while(personqueue.isEmpty() != true) {
temp = personqueue.poll();
int ans = dis.get(temp);
int index = 0;
while(index < temp.getFriends().size()) {
if(temp.getFriends().get(index).visit == true) {
index++;
continue;
}
temp.getFriends().get(index).visit = true;
personqueue.offer(temp.getFriends().get(index));
dis.put(temp.getFriends().get(index),ans + 1);
if(temp.getFriends().get(index) == b) {
return dis.get(b);
}
index++;
}
}
return -1;
客户端实现及测试用例
main方法的设计是为了对类设计是否完成功能的一个检查,因此在main方法的设计过程中,应该调用前面设计的addVertex、addEdge、getDistance等方法进行使用,同时通过对实际的输出进行判断,看是否与预期达到的输入一致,以此完成main的设计。
在测试用例的设计中,应当更加全面对各个类中的方法进行测试。例如,在addVertex方法中就需要对是否重名进行判断;在addEdge方法中就需要判断参数是否存在,参数是否同一个人,这两个人是否已经有边了;在getDistance方法中,我们需要对特殊情况进行处理,例如输入同一个人,两个人之间无法到达等等特殊情况。