【问题标题】:Dijkstra adjacency listDijkstra 邻接表
【发布时间】:2016-05-13 22:51:49
【问题描述】:

我在将 Dijkstras 算法的伪代码转换为实际代码时遇到了问题。我得到了一个邻接列表,例如“位置 - 相邻位置 - 到位置的距离”,例如一个节点:AAA AAC 180 AAD 242 AAH 40。 我的任务是读取一个按照描述组织为邻接列表的文件,并计算从一个节点到另一个节点的最短路径。 这是 Dijkstra 伪代码:

    void dijkstra( Vertex s )
    {
        for each Vertex v
        {
          v.dist = INFINITY;
          v.known = false;
        }
      s.dist = 0;
        while( there is an unknown distance vertex )
         {
          Vertex v = smallest unknown distance vertex;
          v.known = true;

         for each Vertex w adjacent to v
          if( !w.known )
           {
           DistType cvw = cost of edge from v to w;
           if( v.dist + cvw < w.dist )
             {
    // Update w
           decrease( w.dist to v.dist + cvw );
           w.path = v;
             }
            }
           }
    }

“对于与 v 相邻的每个顶点 w”这行最麻烦 这是我的非工作代码:

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;

public class Dijkstra {

    public static boolean isInteger(String s) {
        return isInteger(s, 10);
    }

    public static boolean isInteger(String s, int radix) {
        if (s.isEmpty())
            return false;
        for (int i = 0; i < s.length(); i++) {
            if (i == 0 && s.charAt(i) == '-') {
                if (s.length() == 1)
                    return false;
                else
                    continue;
            }
            if (Character.digit(s.charAt(i), radix) < 0)
                return false;
        }
        return true;
    }

    public static void dijkstra(Vertex[] a, Vertex s, int lineCount) {
        int i = 0;
        while (i < (lineCount)) // each Vertex v
        {
            a[i].dist = Integer.MAX_VALUE;
            a[i].known = false;
            i++;
        }

        s.dist = 0;
        int min = Integer.MAX_VALUE; //

        while (!(a[0].known == true && a[1].known == true && a[2].known == true && a[3].known == true
                && a[4].known == true && a[5].known == true && a[6].known == true && a[7].known == true
                && a[8].known == true && a[9].known == true && a[10].known == true && a[11].known == true
                && a[12].known == true)) {
            System.out.println("here");
            for (int b = 0; b < lineCount; b++) {

                if (a[b].dist < min && a[b].known == false) {
                    min = a[b].dist;
                }
            }
            int c = 0;
            while (c < lineCount) {

                if (a[c].dist == min && a[c].known == false) {
                    break;
                }
                c++;
            }
            System.out.println(min);

            a[c].known = true;
            int adjSize = a[c].adj.size();

            int current = 0;

            System.out.println(adjSize);

            while (current < adjSize - 1) {

                String currentAdjacent = (String) a[c].adj.get(current);
                int p = 0;

                while (p < lineCount) {
                    if (a[p].name.equals(currentAdjacent)) {

                        if (!a[p].known) {
                            String cvwString = (String) a[c].distance.get(current);
                            int cvw = Integer.parseInt(cvwString);
                            System.out.println(" This is cvw" + cvw);
                            System.out.println("Here2");

                            if (a[c].dist + cvw < a[p].dist) {
                                a[p].dist = a[c].dist + cvw;
                                a[p].path = a[c];
                            }
                        }
                    }
                    p++;
                }
                current++;
            }
        }
    }

    public static class Vertex {
        public List adj; // Adjacency list
        public List distance;
        public boolean known;
        public int dist; // DistType is probably int
        public Vertex path;
        public String name;

        // Other fields and methods as needed
    }

    public static void printPath(Vertex v) {
        if (v.path != null) {
            printPath(v.path);
            System.out.print(" to ");
        }
        System.out.print(v);
    }

    public static void main(String[] args) throws IOException {

        int lineCounter = 0;

        BufferedReader br = new BufferedReader(new FileReader("airport.txt"));
        try {
            StringBuilder sb = new StringBuilder();
            String line = br.readLine();

            while (line != null) {

                sb.append(line);
                sb.append(System.lineSeparator());
                line = br.readLine();

                lineCounter = lineCounter + 1;
            }

            Vertex[] arr = new Vertex[lineCounter];
            for (int i = 0; i < lineCounter; i++) {
                arr[i] = new Vertex();
                arr[i].adj = new LinkedList<String>();
                arr[i].distance = new LinkedList<Integer>();
            }
            ;

            //
            int arrayCounter = 0;
            String everything = sb.toString();
            String[] lines = everything.split("\\s*\\r?\\n\\s*");

            for (String line1 : lines) {
                arr[arrayCounter] = new Vertex();

                arr[arrayCounter].adj = new LinkedList<String>();
                arr[arrayCounter].distance = new LinkedList<Integer>();
                String[] result = line1.split("\\s+");

                for (int x = 0; x < result.length; x++) {
                    if (x == 0) {
                        arr[arrayCounter].name = result[0];
                        continue;
                    } else if (isInteger(result[x])) {
                        arr[arrayCounter].distance.add(result[x]);
                        continue;
                    } else {
                        arr[arrayCounter].adj.add(result[x]);
                        continue;
                    }
                }

                arrayCounter++;
            }

            for (int i = 0; i < 12; i++) {
                System.out.println(arr[i].name);
            }
            System.out.println(lineCounter);
            dijkstra(arr, arr[3], lineCounter - 1);
            printPath(arr[11]);

        } finally {
            br.close();
        }
    }
}

使用我的顶点类,我首先使用一系列while循环,遍历存储在链表中的邻接字符串,同时比较查看哪个顶点等效于邻接列表字符串。有没有更好的方法来使用我的 Vertex 类对“与 v 相邻的每个 Vertex w”进行编码?并为我可能犯的凌乱的代码和任何其他风格的罪行道歉。谢谢!

【问题讨论】:

  • 没有缩进的嵌套结构使代码几乎不可读。请考虑更正第一个代码块的格式。
  • 好的,现在应该更好地格式化。
  • 为什么不直接使用s.matches("^-?[0-9]+") 实现isInteger?为什么需要考虑基数? (除了 10 之外,你从不传递任何东西,隐含地)
  • @panzerschwein 缩进仍然很差。请格式化所有代码。
  • 初学者,但这似乎更简洁。

标签: java algorithm dijkstra adjacency-list


【解决方案1】:

要解决这个问题,您需要一堆“节点”对象,存储在 HashMap 中,以 Source Location 为键。

在节点中,您需要一组对相邻“节点”对象(或至少是它们的“键”)的引用,以便您可以针对它编写逻辑。“节点”还需要知道它的位置和到每个“节点”的距离相邻”节点。想想伦敦地铁地图 - 每个车站至少连接一个其他车站。通常两个或更多。因此,与地铁站相邻的节点是您可以从该车站到达的下一站。

一旦您有了该数据结构,您就可以使用递归例程来遍历每个单独的节点。然后它应该遍历每个子节点(又名相邻节点),并通过将这些数据存储在 HashMap 中并在递归(或“遍历”图)时使用当前累积距离来跟踪从初始(源)节点到当前节点的距离")。递归时,此跟踪信息应该是您的方法签名的一部分。您还需要跟踪递归时所采用的当前路径,以避免循环循环(具有讽刺意味的是,这最终会导致 StackOverflowError)。您可以通过使用 HashSet 来做到这一点。这个 Set 应该跟踪源节点和当前节点的位置作为入口键。如果你在递归期间看到这个存在,那么你已经看到它了,所以不要继续处理。

我不会为您编写解决方案的代码,因为我怀疑您在理解答案的过程中会提出更具体的问题,而这些问题很可能在其他地方得到解答。

【讨论】:

    猜你喜欢
    • 2014-04-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-10
    • 1970-01-01
    • 2013-01-20
    • 1970-01-01
    • 2017-11-04
    • 1970-01-01
    相关资源
    最近更新 更多