简体   繁体   English

找到两个节点之间的最短距离

[英]Finding the shortest distance between two nodes

I found and implemented Dijkstra's algorithm into a graph that I had created - which shows a map of my local area 我发现并实现了Dijkstra算法到我创建的图形中 - 它显示了我本地区域的地图 在此输入图像描述

The code works fine but I want it to display all the nodes that it visited in order to get to the location Node from the source node. 代码工作正常,但我希望它显示它访问的所有节点,以便从源节点到达位置节点。 So for example: if I set the source node at 1 (Banstead), and the location node to 4 (Whteleafe) - I want it to perhaps store in an array the nodes it visited like Array = {1,2,4} Any ideas? 例如:如果我将源节点设置为1(Banstead),并将位置节点设置为4(Whteleafe) - 我希望它可能将它所访问的节点存储在数组中,如Array = {1,2,4}想法? I want to put this on an FXML file and have the nodes as ellipses and connecting them with lines - but in order to do so I need to store that values of the nodes visited. 我想把它放在一个FXML文件上,并将节点作为省略号并用线连接它们 - 但为了做到这一点,我需要存储所访问节点的值。

package dijkstras;

public class Dijkstras {

    static class createGraph{
        int vertices;
        int matrix[][];

        public createGraph(int vertex){

            this.vertices = vertex;
            matrix = new int[vertex][vertex];
        }

        public void edge(int source, int destination, int weight){

            matrix[source][destination] = weight;
            matrix[destination][source] = weight;
        }

        int getMinVertex(boolean [] mst, int [] key){
            int minKey = Integer.MAX_VALUE;
            int vertex = -1;
            for (int i = 1; i < vertices; i++) {
                if(mst[i]==false && minKey>key[i]){
                    minKey = key[i];
                    vertex =i;
                }
            }

            return vertex;  
        }

        public void dijkstras(int sourceVertex){
            boolean[] spt = new boolean[vertices];
            int [] distance = new int[vertices];
            int infinity = Integer.MAX_VALUE;

            //setting all distances to infinity
            for(int i=1; i<vertices; i++){
                distance[i] = infinity;
            }

            //test for starting vertext = 1
            distance[sourceVertex] = 1;

            //create tree
            for(int i=1; i<vertices; i++){

                int vertexU = getMinVertex(spt, distance);

                spt[vertexU] = true;   
                //go through all possible paths adjacent to vertex
                for(int vertexV=1; vertexV<vertices; vertexV++){
                    //check if edge between Vu and Vv exists
                    if(matrix[vertexU][vertexV]>0){

                        //checks vertexV exists and if distance is not infinite
                        if(spt[vertexV]==false && matrix[vertexU][vertexV]!=infinity){

                            int newKey = matrix[vertexU][vertexV] + distance[vertexU];
                            if(newKey<distance[vertexV])
                                distance[vertexV] = newKey;
                        }
                    }
                }
            }

            System.out.println();      
            printDijkstras(sourceVertex, distance);
        }

        public void printDijkstras(int sourceVertex, int [] key){
            System.out.println("Dijkstra Algorithm:");
            int LocationOfChosenUser = 10;  
            System.out.println("Source Vertex: "+ sourceVertex + " to " +
              LocationOfChosenUser + " distance: " + (key[LocationOfChosenUser]-1));
        }
    }

    public static void graph() {
       int vertices = 18;
       createGraph graph = new createGraph(vertices);
       int sourceVertex = 8;
       //adding all nodes
       graph.edge(1,2,4);   graph.edge(1,17,3); 
       graph.edge(2,1,4);   graph.edge(2,4,4);   graph.edge(2,10,5); 
       graph.edge(3,4,1);   graph.edge(3,6,5);   graph.edge(3,5,2);
       graph.edge(4,2,4);   graph.edge(4,3,1);   graph.edge(4,5,2); 
       graph.edge(5,4,2);   graph.edge(5,3,2);   graph.edge(5,6,3);  graph.edge(5,9,4);  graph.edge(5,10,5); 
       graph.edge(6,3,5);   graph.edge(6,5,3);   graph.edge(6,7,2);  graph.edge(6,9,2);
       graph.edge(7,6,2);   graph.edge(7,8,5);   
       graph.edge(8,7,5);   graph.edge(8,9,4);   graph.edge(8,12,5);
       graph.edge(9,5,4);   graph.edge(9,8,4);   graph.edge(9,11,5); graph.edge(9,6,2); 
       graph.edge(10,2,5);  graph.edge(10,5,5);  graph.edge(10,13,1);graph.edge(10,14,3); graph.edge(10,17,6);
       graph.edge(11,9,5);  graph.edge(11,12,3); graph.edge(11,13,3);
       graph.edge(12,8,5);  graph.edge(12,11,3); graph.edge(12,15,4);
       graph.edge(13,11,3); graph.edge(13,10,1); graph.edge(13,14,2);
       graph.edge(14,10,3); graph.edge(14,13,2); graph.edge(14,16,6); graph.edge(14,15,6);
       graph.edge(15,12,4); graph.edge(15,14,5); graph.edge(15,16,9); 
       graph.edge(16,15,9); graph.edge(16,17,1); graph.edge(16,14,6);
       graph.edge(17,1,3);  graph.edge(17,16,1);

       graph.dijkstras(sourceVertex);
    }
    public static void main(String[] args){
        graph();
    }
}

As you can see I set the sourceVertex to 8 and the LocationVertex (LocationOfChosenUser) to 10. and the output looks something like this: 如您所见,我将sourceVertex设置为8,将LocationVertex(LocationOfChosenUser)设置为10.输出如下所示:

 Dijkstra Algorithm:
Source Vertex: 8 to 10 distance: 12

Easiest way of doing this is to just keep track of the predecessors of each node. 最简单的方法是跟踪每个节点的前驱。 When you've reached the end node you can then backtrack to find out where you came from. 当您到达终点节点后,您可以回溯以找出您的来源。

Add initialization 添加初始化

int [] comeFrom = new int[vertices];

Change 更改

if(newKey<distance[vertexV])
    distance[vertexV] = newKey;

to

if(newKey<distance[vertexV]) {
    distance[vertexV] = newKey;
    comeFrom[vertexV] = vertexU;
}

and when printing out 打印出来的时候

List<Integer> path = new ArrayList();
int pos = LocationOfChosenUser;

while(pos != sourceVertex) {
   path.add(pos);
   pos = comeFrom[pos];
}

for (int i=path.size()-1; i>=0; i--) {
   System.out.print(path.get(i));
   if (i > 0) System.out.print(" -> ");
}

Every time you update your distance array, you need to keep track of what path was taken to reach the node. 每次更新距离数组时,都需要跟踪到达节点的路径。 This can be done several ways, and I recommend an array that stores which step was taken to achieve the distance in the distance array. 这可以通过多种方式完成,我建议使用一个数组来存储采取哪个步骤来实现距离数组中的距离。

distance[vertexV] = newKey;
lastStep[vertexV] = vertexU;

When the algorithm is done, you can then traverse the path from the destination back to the start. 算法完成后,您可以遍历从目标返回到开始的路径。 Basically, you do this: 基本上,你这样做:

int location = LocationOfChosenUser;
System.out.print(LocationOfChosenUser);
while (location != sourceVertex) {
    location = lastStep[LocationOfChosenUser];
    System.out.print(" <- " + location);
}
System.out.println();

This order gives you the reverse order (therefore, the <- arrow). 此订单为您提供相反的顺序(因此, <-箭头)。 How you would store the numbers and reverse it is left as an exercise for you. 如何存储数字并将其反转将留作练习。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM