Список смежности Дейкстры

У меня возникла проблема с преобразованием псевдокода алгоритма Дейкстраса в реальный код. Мне был предоставлен список смежности, такой как «Местоположение - соседнее местоположение - расстояние до местоположения», пример для одного узла: AAA AAC 180 AAD 242 AAH 40. Моя задача заключалась в том, чтобы прочитать файл, организованный как список смежности, как описано, и вычислить самый короткий путь от одного узла к другому. Вот псевдокод Дейкстры:

    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;
             }
            }
           }
    }

У меня больше всего проблем со строкой «для каждой вершины w, смежной с v». Вот мой нерабочий код:

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, чтобы сначала пройти по строкам смежности, хранящимся в связанном списке, сравнивая, чтобы увидеть, какая вершина эквивалентна строке списка смежности. Есть ли лучший способ закодировать «для каждой вершины w, смежной с v», используя мой класс вершин? И впереди извинения за грязный код и любые другие грехи в стиле, которые я, возможно, совершил. Спасибо!


person panzerschwein    schedule 13.05.2016    source источник
comment
Наличие вложенных структур без отступов делает код почти нечитаемым. Пожалуйста, подумайте об изменении форматирования первого блока кода.   -  person ChiefTwoPencils    schedule 14.05.2016
comment
Хорошо, теперь должно быть лучше отформатировано.   -  person panzerschwein    schedule 14.05.2016
comment
Почему бы просто не реализовать isInteger с помощью s.matches("^-?[0-9]+")? Зачем нужно учитывать основание системы счисления? (вы никогда не передаете ничего, кроме 10, неявно)   -  person Andy Turner    schedule 14.05.2016
comment
@panzerschwein отступ по-прежнему оставляет желать лучшего. Пожалуйста, отформатируйте весь код.   -  person Andy Turner    schedule 14.05.2016
comment
Новичок, но это кажется более лаконичным.   -  person panzerschwein    schedule 14.05.2016
comment
@AndyTurner старался изо всех сил, но не думаю, что смогу отформатировать дальше. Это просто нечитабельно? Никто не думает, что они видят мою проблему?   -  person panzerschwein    schedule 14.05.2016
comment
Форматирование вашего кода должно быть очень простым. По крайней мере, позвольте вашей любимой среде IDE отформатировать его за вас, скопируйте, вставьте сюда и, выбрав код, нажмите кнопку { } в строке меню в редакторе.   -  person ChiefTwoPencils    schedule 14.05.2016
comment
@ChiefTwoPencils Хорошо, я использовал формат IDE. Надеюсь, теперь он отформатирован удовлетворительно.   -  person panzerschwein    schedule 14.05.2016


Ответы (1)


Чтобы решить эту проблему, вам понадобится набор объектов «Узел», хранящихся в HashMap, с ключом Source Location.

В узле вам понадобится набор ссылок на соседние объекты «Узел» (или, по крайней мере, их «ключ», чтобы вы могли написать логику для него. «Узлу» также необходимо знать свое местоположение и расстояние до каждого «соседнего» узла. • Подумайте о картах метро Lundon Underground Tube Maps - каждая станция соединяется по крайней мере с одной другой станцией. Обычно с двумя или более. Таким образом, соседние узлы со станциями метро являются ближайшими остановками, до которых вы можете добраться от этой станции.

Когда у вас есть эта структура данных, вы можете использовать рекурсивную процедуру для итерации по каждому отдельному узлу. Затем он должен перебирать каждый дочерний узел (также известный как соседний узел) и отслеживать расстояния от начального (исходного) узла до текущего узла, сохраняя эти данные в HashMap и используя текущее накопленное расстояние во время рекурсии (или «обхода» графа. "). Эта отслеживающая информация должна быть частью вашей сигнатуры метода при рекурсии. Вам также необходимо будет отслеживать текущий путь, который вы выбрали при рекурсии, чтобы избежать круговых циклов (которые в конечном итоге и по иронии судьбы вызовут StackOverflowError). Вы можете сделайте это с помощью HashSet. Этот набор должен отслеживать местоположение исходного и текущего узла в качестве ключа входа. Если вы видите это во время рекурсии, значит, вы уже видели это, поэтому не продолжайте обработку.

Я не собираюсь кодировать решение за вас, потому что подозреваю, что вы задаете более конкретные вопросы, работая над пониманием ответа, на которые, скорее всего, ответят в другом месте.

person user924272    schedule 14.05.2016