在lab2中对lab1中的算法进行了替换,下文给出对比。
Lab1:
在lab1中,利用的是深搜算法计算两个人之间在关系网中的距离。处理流程分两步,为:
1)先在关系网中搜索这两个人,检查是否存在;
2)带入深搜算法中,获得距离
代码如下:
public int getDistance(Person name1, Person name2)
{
if(this.firstperson == null)
{
System.out.println("关系网中没有人!");
return -1;
}
else
{
Vertex tempPerson1 = this.firstperson;
do{//找第一个人
if(tempPerson1.NameString == name1.name)
break;
tempPerson1 = tempPerson1.nextperson;
}while(tempPerson1 != null);
if(tempPerson1 == null)
{
System.out.println("没有找到名为"+name1.name+"的人!");
return -1;
}
if(name1.name == name2.name) return 0;
Vertex tempPerson2 = this.firstperson;
do{//找第二个人
if(tempPerson2.NameString == name2.name)
break;
tempPerson2 = tempPerson2.nextperson;
}while(tempPerson2 != null);
if(tempPerson2 == null)
{
System.out.println("没有找到名为"+name2.name+"的人!");
return -1;
}
int distance = 1,result = 0;
Friendship tempShip = tempPerson1.friendship;
if (tempShip == null) return -1;//这个人没有朋友
result = DFS(tempShip, distance, name2.name,name1.name);
this.reset();
return result;
}
}
public int DFS(Friendship tempShip, int distance, String name, String name2)
{
boolean flag1 = false, flag2 = false;
int distance2 = 0,distance1 = 100;
do {
if(tempShip.itsfriend.visited ==true)//这个人已经遍历过了
tempShip = tempShip.nextfriend;//准备遍历下一个朋友
else//没有遍历过
{
if(tempShip.friendsname == name)//找到了
{
flag1 = true;
break;
}
else if(tempShip.friendsname == name2)//找到自己了
{
tempShip = tempShip.nextfriend;//准备遍历下一个朋友
continue;
}
else//没找到
{
tempShip.itsfriend.visited = true;
distance2 = DFS(tempShip.itsfriend.friendship, distance+1, name,name2);
if(distance != -1)
{
if(flag2 == false)
{
flag2 = true;
distance1 = distance2;
}
else
{
if(distance1 > distance2) distance1 = distance2;
}
}
tempShip = tempShip.nextfriend;//准备遍历下一个朋友
}
}
}while(tempShip != null);//直到搜完这个人的所有朋友
if(flag1 == true)
{
if(flag2 == false) return distance;
else if(distance > distance1) return distance1;
else return distance;
}
else
{
if(flag2 == true) return distance1;
else return -1;
}
}
public boolean reset()
{
Vertex re = this.firstperson;
if (re == null) return true;
do
{
re.visited = false;
re = re.nextperson ;
}while(re != null);
return true;
}
在函数最后还有reset方法,用于重置代表是否访问的标志。
可以发现,代码量过长,并且写的很繁琐。主要问题在于查找两人是否存在时需要两次遍历关系网,效率低下。
搜索算法的修改是最为明显的。除此之外还有其他的修改,例如最初的设计中,在FriendshipGraph里建立了多个变量,这些变量实际上使用的次数并不多,但又找不到更好的替代方法。这些都在使用lab2中的图的功能后做出了修改。
public Vertex lastperson;//保存最后一个人
public Vertex firstperson;//保存第一个人
public class Vertex
{
String NameString;//存放当前结点的人
int friendnum = 0;//存放这个人的朋友数量
Friendship friendship;
Vertex nextperson;//指向下一个人
boolean visited = false;
}
public class Friendship//存放这个人的关系
{
String friendsname;
Vertex itsfriend;//指向这个人的朋友在关系表中的位置
Friendship nextfriend;
}
public FriendshipGraph()
{
this.lastperson = null;
this.firstperson = null;
}
Lab2:
lab2使用了在实验前半部分实现的图的各项功能,并且对冗余的遍历进行优化。直接使用contains方法就可以查找,不再需要遍历。
此外,在lab1中的搜索算法中,每当遍历一个人时,需要在图中找到这个人的结点,然后对它的关系网进行遍历。在lab2中,可以直接使用targets方法直接获得和该点相连接的结点,不再需要遍历操作。
需要注意的是,函数最后的reset函数也要做些许修改,因为使用的图的构建方式做了修改。
代码如下:
public int getDistance(Person name1, Person name2)//获得两个人之间的距离
{
if(personGraph == null)
{
System.out.println("关系网中没有人!");
return -1;
}
else
{
//检查有这俩人
if(personGraph.vertices().contains(name1) && personGraph.vertices().contains(name2))//有这俩人
{
if(name1.name == name2.name)//自己与自己的距离
return 0;
Person temp = null;//保留第一个人
for(Person each : personGraph.vertices())
{
if(each.name == name1.name)
{
temp = each;
break;
}
}
int result = 0,distance = 1;
result = DFS(temp, distance, name2.name,name1.name);
this.reset();
return result;
}
else
return -1;
}
}
public int DFS(Person temp, int distance, String name, String name2)//深搜,获得距离时使用
{
boolean flag1 = false, flag2 = false;
int distance2 = 0,distance1 = 100;
Map<Person, Integer> ASsource = new HashMap<>();
ASsource = personGraph.targets(temp);
for(Person each : ASsource.keySet())
{
if(each.visited == true)//这个人已经遍历过了
continue;
if(each.name == name)//找到了
{
flag1 = true;
break;
}
else
{
each.visited = true;
distance2 = DFS(each,distance+1,name,name2);
if(distance2 != -1)//找到了
{
if(flag2 == false)
{
flag2 = true;
distance1 = distance2;
}
else
{
if(distance1 > distance2) distance1 = distance2;
}
}
}
}
if(flag1 == true)
{
if(flag2 == false)
{
return distance;
}
else if(distance > distance1)
{
return distance1;
}
else return distance;
}
else
{
if(flag2 == true) return distance1;
else return -1;
}
}
public boolean reset()//重新设置访问状态,以便于下次使用
{
if(personGraph == null)
return true;
for(Person each : personGraph.vertices())
{
each.visited = false;
}
return true;
}
针对lab1中的多个低效率变量,也同样做出了修改。由于可以直接调用已实现的代码,大多数变量都进行了删除,并且还简化了图的创建过程、搜寻结点过程和增加结点过程(之前是需要遍历操作的,现在就不需要了)。
private final ConcreteEdgesGraph<Person> personGraph;
public FriendshipGraph() {
personGraph = new ConcreteEdgesGraph<>();
}
public boolean searchVertex(Person name)//找这个人
{
return personGraph.vertices().contains(name);
}
public boolean searchFriendship(Person name1,Person name2)//寻找某个人的某个朋友
{
if(searchVertex(name1) == false || searchVertex(name2) == false)
return false;
Map<Person, Integer> ASsource = new HashMap<>();
ASsource = personGraph.targets(name1);
if(ASsource.containsKey(name2))
{
return true;
}
return false;
}
public void addVertex(Person name)//增加一个人
{
personGraph.add(name);
}
public void addEdge(Person name1, Person name2)//建立两个人之间的关系
{
personGraph.set(name1, name2, 1);
}