计算到其他相同类型节点的距离
Calculate distance to other node of same type
我正在编写一个程序来计算 2 个节点(本例中的人)彼此之间的距离。
public class Person() {
private Set<Person> persons;
public int calculateDistanceTo(Person person) {
// how to do this
}
我尝试使用递归。但这会导致程序无休止地继续下去。
这是(无效代码)。
public int calculateDistanceTo(Person person, int count) {
if (persons.contains(person)) return 0;
for (Person p : persons) {
count += p.calculateDistanceTo(p, ++count);
}
return count;
}
(public class Person() 在 Java 中语法不正确)
首先,让我们看看下面的循环在做什么:
for (Person p : persons) {
count += p.calculateDistanceTo(p, ++count);
}
以如下关系为例:
在上面的例子中,设 1 为 p1,2 为 p2,等等。P1 和 P4 没有链接,所以当你这样做时:
p1.calculateDistanceTo(p4, 0);
递归堆栈为:
calculateDistanceTo(2,1)
calculateDistanceTo(1,2)
calculateDistanceTo(2,3)
… infinite
这就是你进入无限循环的原因。
更正:
1)如果一个人被访问过,你需要给一个人添加一个标志
2)应该用for循环来判断被访人到目标人的最短距离
所以本质上,它是一种深度优先搜索,通过一些比较来给出最短路径。 (当然,要在一个距离内找到最短路径,我们应该使用广度优先搜索。但是我根据你给出的解决方案推导出深度优先搜索)
例如:
public class Person {
private Set<Person> friends;
int id;
boolean visited = false;
public Person(int id) {
this.id = id;
friends = new HashSet<>();
}
public Set<Person> getFriends() {
return friends;
}
@Override
public String toString() {
return id + "";
}
public boolean equals(Object o) {
return ((Person) o).id == this.id;
}
public int calculateDistanceTo(Person person) {
this.visited = true;
if (friends.contains(person)) return 0;
int shortestDistance = Integer.MAX_VALUE / 2;
for (Person friend : friends) {
if (!friend.visited) {
int dist = friend.calculateDistanceTo(person);
if (dist < shortestDistance) {// finding the shortest distance
shortestDistance = dist;
}
}
}
return 1 + shortestDistance;
}
static Person p1 = new Person(1);
static Person p2 = new Person(2);
static Person p3 = new Person(3);
static Person p4 = new Person(4);
static Person p5 = new Person(5);
public static void main(String[] args) {
List<Person> persons = new ArrayList<>(Arrays.asList(p1, p2, p3, p4, p5));
p1.getFriends().add(p2);
p1.getFriends().add(p3);
p2.getFriends().add(p1);
p2.getFriends().add(p3);
p3.getFriends().add(p1);
p3.getFriends().add(p2);
p3.getFriends().add(p5);
p5.getFriends().add(p3);
int dist = p1.calculateDistanceTo(p4);
System.out.println(dist); // 1073741824 means no relation
for (Person p : persons) p.visited = false;// clear flag
dist = p1.calculateDistanceTo(p2);
System.out.println(dist); // 0
for (Person p : persons) p.visited = false;// clear flag
dist = p1.calculateDistanceTo(p5);
System.out.println(dist); // 1
}
}
BOND的答案是可行的,但是在实现上有一个很大的问题:对象的内部状态会在计算过程中被修改。在多线程环境中,这将导致意外行为。所以这是我的解决方案。
首先是 class 人(我存储了一个名字并调用了集合 'neighbours':
public class Person {
private final Set<Person> neighbours = new HashSet<>();
private final String name;
public Person(String name) {
this.name = name;
}
public void addNeighbour(Person p)
{
neighbours.add(p);
p.neighbours.add(this);
}
public int calculateDistanceTo(Person p)
{
return calculateDistanceTo(p, 0, Collections.emptySet());
}
private int calculateDistanceTo(Person person, int count, Set<Person> tried)
{
if (neighbours.contains(person))
return count;
Set<Person> nextTry = new HashSet<>(tried);
nextTry.add(this);
return neighbours.stream()
.filter(p -> !nextTry.contains(p))
.mapToInt(p -> p.calculateDistanceTo(person, count+1, nextTry))
.filter(i -> i>=0)
.findFirst()
.orElse(-1);
}
@Override
public String toString() {
return "Person{" + "name=" + name + '}';
}
}
我正在创建一组我已经尝试过的人,并将此集合放入 calculateDistanceTo 方法中。如果两个人没有联系,我的方法将 return -1。所以我的 main() 方法将如下所示:
public static void main(String ... args)
{
Person p1 = new Person("Anton");
Person p2 = new Person("Berta");
Person p3 = new Person("Charlie");
Person p4 = new Person("Dora");
Person p5 = new Person("Emil");
p1.addNeighbour(p2);
p1.addNeighbour(p3);
p2.addNeighbour(p3);
p3.addNeighbour(p5);
System.out.println("Distance from Anton to Dora = "+p1.calculateDistanceTo(p4)); // -1
System.out.println("Distance from Anton to Berta = "+p1.calculateDistanceTo(p2)); // 0
System.out.println("Distance from Anton to Emil = "+p1.calculateDistanceTo(p5)); // 1
}
编辑 如您所见,没有必要实现 equals() 和 hashCode(),因为我们这里只使用引用。
我正在编写一个程序来计算 2 个节点(本例中的人)彼此之间的距离。
public class Person() {
private Set<Person> persons;
public int calculateDistanceTo(Person person) {
// how to do this
}
我尝试使用递归。但这会导致程序无休止地继续下去。
这是(无效代码)。
public int calculateDistanceTo(Person person, int count) {
if (persons.contains(person)) return 0;
for (Person p : persons) {
count += p.calculateDistanceTo(p, ++count);
}
return count;
}
(public class Person() 在 Java 中语法不正确)
首先,让我们看看下面的循环在做什么:
for (Person p : persons) {
count += p.calculateDistanceTo(p, ++count);
}
以如下关系为例:
在上面的例子中,设 1 为 p1,2 为 p2,等等。P1 和 P4 没有链接,所以当你这样做时:
p1.calculateDistanceTo(p4, 0);
递归堆栈为:
calculateDistanceTo(2,1)
calculateDistanceTo(1,2)
calculateDistanceTo(2,3)
… infinite
这就是你进入无限循环的原因。
更正: 1)如果一个人被访问过,你需要给一个人添加一个标志 2)应该用for循环来判断被访人到目标人的最短距离
所以本质上,它是一种深度优先搜索,通过一些比较来给出最短路径。 (当然,要在一个距离内找到最短路径,我们应该使用广度优先搜索。但是我根据你给出的解决方案推导出深度优先搜索)
例如:
public class Person {
private Set<Person> friends;
int id;
boolean visited = false;
public Person(int id) {
this.id = id;
friends = new HashSet<>();
}
public Set<Person> getFriends() {
return friends;
}
@Override
public String toString() {
return id + "";
}
public boolean equals(Object o) {
return ((Person) o).id == this.id;
}
public int calculateDistanceTo(Person person) {
this.visited = true;
if (friends.contains(person)) return 0;
int shortestDistance = Integer.MAX_VALUE / 2;
for (Person friend : friends) {
if (!friend.visited) {
int dist = friend.calculateDistanceTo(person);
if (dist < shortestDistance) {// finding the shortest distance
shortestDistance = dist;
}
}
}
return 1 + shortestDistance;
}
static Person p1 = new Person(1);
static Person p2 = new Person(2);
static Person p3 = new Person(3);
static Person p4 = new Person(4);
static Person p5 = new Person(5);
public static void main(String[] args) {
List<Person> persons = new ArrayList<>(Arrays.asList(p1, p2, p3, p4, p5));
p1.getFriends().add(p2);
p1.getFriends().add(p3);
p2.getFriends().add(p1);
p2.getFriends().add(p3);
p3.getFriends().add(p1);
p3.getFriends().add(p2);
p3.getFriends().add(p5);
p5.getFriends().add(p3);
int dist = p1.calculateDistanceTo(p4);
System.out.println(dist); // 1073741824 means no relation
for (Person p : persons) p.visited = false;// clear flag
dist = p1.calculateDistanceTo(p2);
System.out.println(dist); // 0
for (Person p : persons) p.visited = false;// clear flag
dist = p1.calculateDistanceTo(p5);
System.out.println(dist); // 1
}
}
BOND的答案是可行的,但是在实现上有一个很大的问题:对象的内部状态会在计算过程中被修改。在多线程环境中,这将导致意外行为。所以这是我的解决方案。
首先是 class 人(我存储了一个名字并调用了集合 'neighbours':
public class Person {
private final Set<Person> neighbours = new HashSet<>();
private final String name;
public Person(String name) {
this.name = name;
}
public void addNeighbour(Person p)
{
neighbours.add(p);
p.neighbours.add(this);
}
public int calculateDistanceTo(Person p)
{
return calculateDistanceTo(p, 0, Collections.emptySet());
}
private int calculateDistanceTo(Person person, int count, Set<Person> tried)
{
if (neighbours.contains(person))
return count;
Set<Person> nextTry = new HashSet<>(tried);
nextTry.add(this);
return neighbours.stream()
.filter(p -> !nextTry.contains(p))
.mapToInt(p -> p.calculateDistanceTo(person, count+1, nextTry))
.filter(i -> i>=0)
.findFirst()
.orElse(-1);
}
@Override
public String toString() {
return "Person{" + "name=" + name + '}';
}
}
我正在创建一组我已经尝试过的人,并将此集合放入 calculateDistanceTo 方法中。如果两个人没有联系,我的方法将 return -1。所以我的 main() 方法将如下所示:
public static void main(String ... args)
{
Person p1 = new Person("Anton");
Person p2 = new Person("Berta");
Person p3 = new Person("Charlie");
Person p4 = new Person("Dora");
Person p5 = new Person("Emil");
p1.addNeighbour(p2);
p1.addNeighbour(p3);
p2.addNeighbour(p3);
p3.addNeighbour(p5);
System.out.println("Distance from Anton to Dora = "+p1.calculateDistanceTo(p4)); // -1
System.out.println("Distance from Anton to Berta = "+p1.calculateDistanceTo(p2)); // 0
System.out.println("Distance from Anton to Emil = "+p1.calculateDistanceTo(p5)); // 1
}
编辑 如您所见,没有必要实现 equals() 和 hashCode(),因为我们这里只使用引用。