Java 查找两个位置之间的最短路径(未加权和使用BFS)
使用BFS的最短路径Java 查找两个位置之间的最短路径(未加权和使用BFS),java,shortest-path,breadth-first-search,Java,Shortest Path,Breadth First Search,使用BFS的最短路径 public static LinkedList<String> findShortestPath(String start, String end) { LinkedList<String> bfsList = new LinkedList<String>(); Queue<Actor> queue = new LinkedList<Actor>(); Map<String, Ac
public static LinkedList<String> findShortestPath(String start, String end) {
LinkedList<String> bfsList = new LinkedList<String>();
Queue<Actor> queue = new LinkedList<Actor>();
Map<String, Actor> prev = new HashMap<String, Actor>();
Actor current = graph.getActorsByName().get(start);
queue.add(current);
current.setVisited(true);
while(!queue.isEmpty()) {
current = queue.remove();;
if(current.getName().equals(end)) {
break;
} else {
for(int i = 0; i < current.getFriends().size(); i++) {
if(current.getFriends().get(i).getVisited() == false) {
queue.add(graph.getActorsByName().get(current.getFriends().get(i).getName()));
graph.getActorsByName().get(current.getFriends().get(i).getName()).setVisited(true);
prev.put(current.getFriends().get(i).getName(), current);
}
}
}
}
if(!current.getName().equals(end)) {
System.out.println("\nThere is no path between " + start + " and " + end);
}
for(Map.Entry<String, Actor> entry : prev.entrySet()) {
String key = entry.getKey();
bfsList.add(key);
}
return bfsList;
}
公共静态LinkedList FindShortPath(字符串开始,字符串结束){
LinkedList bfsList=新建LinkedList();
Queue Queue=new LinkedList();
Map prev=新的HashMap();
Actor current=graph.getActorsByName().get(开始);
queue.add(当前);
当前.setvisted(true);
而(!queue.isEmpty()){
当前=队列。删除();;
if(current.getName().equals(end)){
打破
}否则{
对于(int i=0;i
上面是我用来尝试在图形中找到两点之间的最短路径的代码。它没有给我这两点之间的正确路径,我也不知道为什么。我已经建立了一个测试平台,我希望演员有名字和一些朋友。这些直接的朋友也有互惠关系 在这个测试中,我在寻找“詹姆斯”和“玛丽”之间的最短路径 在您的实现中,您已经初始化了
prev=new HashMap()
,然后添加每个访问的节点(不仅仅是指示最短路径的节点)。您需要使用prev
作为一种链表。。。例如:
for (Actor node = graph.get(end); node != null; node = prev.get(node.getName())) {
bfsList.add(node.getName());
}
Collections.reverse(bfsList);
用于测试目的的完整更新代码 最短路径实现 仅对原始过帐进行了较小的编辑:
- 输入
作为参数图形
- 通过提取变量简化内环逻辑
- 如果找不到路径,则返回空列表
- 修复了分析找到的最短路径的哈希映射循环
- 添加了用于测试的Actor类
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Queue;
public class ShortestPath {
public static List<String> findShortestPath(Map<String, Actor> graph, String start,
String end) {
LinkedList<String> bfsList = new LinkedList<>();
Queue<Actor> queue = new LinkedList<>();
Map<String, Actor> prev = new HashMap<>();
Actor current = graph.get(start);
queue.add(current);
current.setVisited(true);
while (!queue.isEmpty()) {
current = queue.remove();
if (current.getName().equals(end)) {
break;
} else {
LinkedList<Actor> currentFriends = current.getFriends();
for (Actor currentFriend : currentFriends) {
if (!currentFriend.getVisited()) {
queue.add(currentFriend);
currentFriend.setVisited(true);
prev.put(currentFriend.getName(), current);
}
}
}
}
if (!current.getName().equals(end)) {
System.out.println("\nThere is no path between " + start + " and " + end);
return Collections.emptyList();
}
for (Actor node = graph.get(end); node != null; node = prev.get(node.getName())) {
bfsList.add(node.getName());
}
Collections.reverse(bfsList);
return bfsList;
}
static class Actor {
private final String name;
private final LinkedList<Actor> friends = new LinkedList<>();
private boolean visited;
Actor(String name) {
this.name = name;
}
public void setVisited(boolean visited) {
this.visited = visited;
}
// Would normally be `isVisited`
public boolean getVisited() {
return visited;
}
public String getName() {
return name;
}
public LinkedList<Actor> getFriends() {
return friends;
}
public void addFriend(Actor actor) {
this.friends.add(actor);
}
}
}
import java.util.Collections;
导入java.util.HashMap;
导入java.util.LinkedList;
导入java.util.List;
导入java.util.Map;
导入java.util.Queue;
公共类最短路径{
公共静态列表FindShortPath(映射图、字符串开始、,
字符串结束){
LinkedList bfsList=新建LinkedList();
Queue Queue=new LinkedList();
Map prev=新的HashMap();
Actor current=graph.get(开始);
queue.add(当前);
当前.setvisted(true);
而(!queue.isEmpty()){
current=queue.remove();
if(current.getName().equals(end)){
打破
}否则{
LinkedList currentFriends=current.getFriends();
对于(演员currentFriend:currentFriends){
如果(!currentFriend.getVisited()){
添加(currentFriend);
currentFriend.setVisited(true);
prev.put(currentFriend.getName(),当前);
}
}
}
}
如果(!current.getName().equals(end)){
System.out.println(“\n在“+start+”和“+end”之间没有路径);
返回集合。emptyList();
}
for(Actor node=graph.get(end);node!=null;node=prev.get(node.getName())){
添加(node.getName());
}
收藏。反向(bfsList);
返回bfsList;
}
静态类参与者{
私有最终字符串名;
private final LinkedList friends=新建LinkedList();
私人诊所;
参与者(字符串名称){
this.name=名称;
}
已访问的公共void集合(已访问的布尔值){
这是参观过的;
}
//通常会被访问`
公共布尔getVisited(){
回访;
}
公共字符串getName(){
返回名称;
}
公共链接列表getFriends(){
回报朋友;
}
公众朋友(演员){
这个.friends.add(actor);
}
}
}
测试代码
构建测试图并断言在各个节点之间找到了正确的路径
import static org.hamcrest.core.IsEqual.equalTo;
import static org.junit.Assert.assertThat;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.junit.Before;
import org.junit.Test;
public class ShortestPathTest {
Map<String, ShortestPath.Actor> graph = new HashMap<>();
@Before
public void setup() {
newActor("james", "harry", "luke", "john");
newActor("harry", "luke", "mary");
newActor("luke", "john", "hepzibah");
newActor("john", "kate");
newActor("mary", "hepzibah", "mia");
newActor("hepzibah", "richard");
newActor("kate", "martin", "mia");
newActor("mia", "susan");
newActor("richard", "rebecca");
newActor("rebecca", "hannah");
newActor("michelle");
}
private ShortestPath.Actor newActor(String name, String... friends) {
ShortestPath.Actor actor = graph.computeIfAbsent(name, k -> new ShortestPath.Actor(name));
for (String friendsName : friends) {
ShortestPath.Actor friend = newActor(friendsName);
actor.addFriend(friend);
friend.addFriend(actor);
}
return actor;
}
@Test
public void findShortestPath() {
List<String> shortestPath = ShortestPath.findShortestPath(graph, "james", "mary");
assertThat(shortestPath, equalTo(Arrays.asList("james", "harry", "mary")));
}
@Test
public void findLongerShortestPath() {
List<String> shortestPath = ShortestPath.findShortestPath(graph, "james", "mia");
assertThat(shortestPath, equalTo(Arrays.asList("james", "harry", "mary", "mia")));
}
@Test
public void findAnotherShortestPath() {
List<String> shortestPath = ShortestPath.findShortestPath(graph, "harry", "hannah");
assertThat(shortestPath, equalTo(Arrays.asList("harry", "luke", "hepzibah", "richard", "rebecca", "hannah")));
}
@Test
public void findNoPath() {
List<String> shortestPath = ShortestPath.findShortestPath(graph, "james", "michelle");
assertThat(shortestPath, equalTo(Collections.emptyList()));
}
}
导入静态org.hamcrest.core.IsEqual.equalTo;
导入静态org.junit.Assert.assertThat;
导入java.util.array;
导入java.util.Collections;
导入java.util.HashMap;
导入java.util.List;
导入java.util.Map;
导入org.junit.Before;
导入org.junit.Test;
公共类最短路径测试{
映射图=新的HashMap();
@以前
公共作废设置(){
新演员(“詹姆斯”、“哈里”、“卢克”、“约翰”);
新演员(“哈利”、“卢克”、“玛丽”);
新演员(“卢克”、“约翰”、“赫普齐巴”);
新演员(“约翰”、“凯特”);
新演员(“玛丽”、“赫普齐巴”、“米亚”);
新演员(“赫普齐巴”、“理查德”);
新演员(“凯特”、“马丁”、“米娅”);
新演员(“米娅”、“苏珊”);
新演员(“理查德”、“丽贝卡”);
新演员(“丽贝卡”、“汉娜”);
新演员(“米歇尔”);
}
private ShortestPath.Actor newActor(字符串名称、字符串…朋友){
ShortestPath.Actor-Actor=graph.computeIfAbsent(名称,k->newshortestpath.Actor(名称));
用于(字符串friendsName:friends){
最短路径。Actor-friend=newActor(friendsName);
演员。添加朋友(friend);
朋友。添加朋友(演员);
}
回归演员;
}
@试验
public void findShortestPath(){
列表最短路径=Sh
for (Actor node = graph.get(end); node != null; node = prev.get(node.getName())) {
bfsList.add(node.getName());
}
Collections.reverse(bfsList);
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Queue;
public class ShortestPath {
public static List<String> findShortestPath(Map<String, Actor> graph, String start,
String end) {
LinkedList<String> bfsList = new LinkedList<>();
Queue<Actor> queue = new LinkedList<>();
Map<String, Actor> prev = new HashMap<>();
Actor current = graph.get(start);
queue.add(current);
current.setVisited(true);
while (!queue.isEmpty()) {
current = queue.remove();
if (current.getName().equals(end)) {
break;
} else {
LinkedList<Actor> currentFriends = current.getFriends();
for (Actor currentFriend : currentFriends) {
if (!currentFriend.getVisited()) {
queue.add(currentFriend);
currentFriend.setVisited(true);
prev.put(currentFriend.getName(), current);
}
}
}
}
if (!current.getName().equals(end)) {
System.out.println("\nThere is no path between " + start + " and " + end);
return Collections.emptyList();
}
for (Actor node = graph.get(end); node != null; node = prev.get(node.getName())) {
bfsList.add(node.getName());
}
Collections.reverse(bfsList);
return bfsList;
}
static class Actor {
private final String name;
private final LinkedList<Actor> friends = new LinkedList<>();
private boolean visited;
Actor(String name) {
this.name = name;
}
public void setVisited(boolean visited) {
this.visited = visited;
}
// Would normally be `isVisited`
public boolean getVisited() {
return visited;
}
public String getName() {
return name;
}
public LinkedList<Actor> getFriends() {
return friends;
}
public void addFriend(Actor actor) {
this.friends.add(actor);
}
}
}
import static org.hamcrest.core.IsEqual.equalTo;
import static org.junit.Assert.assertThat;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.junit.Before;
import org.junit.Test;
public class ShortestPathTest {
Map<String, ShortestPath.Actor> graph = new HashMap<>();
@Before
public void setup() {
newActor("james", "harry", "luke", "john");
newActor("harry", "luke", "mary");
newActor("luke", "john", "hepzibah");
newActor("john", "kate");
newActor("mary", "hepzibah", "mia");
newActor("hepzibah", "richard");
newActor("kate", "martin", "mia");
newActor("mia", "susan");
newActor("richard", "rebecca");
newActor("rebecca", "hannah");
newActor("michelle");
}
private ShortestPath.Actor newActor(String name, String... friends) {
ShortestPath.Actor actor = graph.computeIfAbsent(name, k -> new ShortestPath.Actor(name));
for (String friendsName : friends) {
ShortestPath.Actor friend = newActor(friendsName);
actor.addFriend(friend);
friend.addFriend(actor);
}
return actor;
}
@Test
public void findShortestPath() {
List<String> shortestPath = ShortestPath.findShortestPath(graph, "james", "mary");
assertThat(shortestPath, equalTo(Arrays.asList("james", "harry", "mary")));
}
@Test
public void findLongerShortestPath() {
List<String> shortestPath = ShortestPath.findShortestPath(graph, "james", "mia");
assertThat(shortestPath, equalTo(Arrays.asList("james", "harry", "mary", "mia")));
}
@Test
public void findAnotherShortestPath() {
List<String> shortestPath = ShortestPath.findShortestPath(graph, "harry", "hannah");
assertThat(shortestPath, equalTo(Arrays.asList("harry", "luke", "hepzibah", "richard", "rebecca", "hannah")));
}
@Test
public void findNoPath() {
List<String> shortestPath = ShortestPath.findShortestPath(graph, "james", "michelle");
assertThat(shortestPath, equalTo(Collections.emptyList()));
}
}