Создайте связанный граф с двумя типами ребер - PullRequest
0 голосов
/ 19 февраля 2020

Я хочу построить график, который связан и может иметь только горизонтальные или вертикальные ребра. Края - это треки / переключатели треков.

  • Существует два типа треков: NormalTrack и TrackSwitch.
    • NormalTrack: startPoint, endPoint.
    • TrackSwitch: startPoint, endPoint, secondEndPoint.
      • Первая конечная точка - это стандартная настройка, которая может быть пройдена (есть команда переключателя установки, которая может изменить настройку переключателя).
  • Все дорожки (переключатель также является дорожкой) имеют уникальный идентификатор, начинающийся с 1.
  • За исключением первой дорожки, начальная или конечная точка всегда должна быть подключена к начальной или конечной точке существующей дорожки. Только одна другая дорожка (обычная дорожка или переключатель дорожки) может быть подключена к точке на дорожке.

Вот пример и то, как будет выглядеть график:

add track (1,1) -> (5,1)
ID -> 1
add switch (5,1) -> (8,1),(5,3)
ID -> 2
add track (1,1) -> (1,-3)
ID -> 3
add track (1,-3) -> (10,-3)
ID -> 4
add track (8,1) -> (10,1)
ID -> 5
add track (10,1) -> (10,-3)
ID -> 6
add track (5,3) -> (8,3)
ID -> 7

Grapj

У меня есть класс Point, который представляет декартову точку, и класс RailNetwork, где я собираюсь реализовать график. В моем классе Register у меня есть Map<Integer, Track> tracks;, в котором я сохраняю все треки. В этом классе я также создал RailNetwork network = new RailNetwork();

. Я уже реализовал командный интерфейс. Теперь я хочу создать железнодорожную сеть.

Может кто-нибудь показать мне, как реализовать этот способ?

РЕДАКТИРОВАТЬ

Вот моя текущая реализация :

public class RailNetwork {
    private Map<Point, List<Point>> edges = new HashMap<>();

    // Add edge (two points)
    public void addEdge(Point firstCoordinate, Point secondCoordinate) {
        edges.computeIfAbsent(firstCoordinate, x -> new ArrayList<>()).add(secondCoordinate);
        edges.computeIfAbsent(secondCoordinate, x -> new ArrayList<>()).add(firstCoordinate);
    }

    // Return all edges
    public List<Point> getEdges(Point node) {
        return Collections.unmodifiableList(edges.get(node));
    }

    // Check if a set of edges is still connected after removing them
    public boolean isConnectedAfterRemoving(Set<Edge> toRemove) {
        Set<Point> notVisited = edges.entrySet()
                .stream()
                .filter(e -> e.getValue().stream().anyMatch(d -> !toRemove.contains(new Edge(e, d)) &&
                        !toRemove.contains(new Edge(d, e))))
                .map(Map.Entry::getKey).collect(java.util.stream.Collectors.toSet());
        if (notVisited.isEmpty())
            return true;
        visit(notVisited.iterator().next(), notVisited, toRemove);
        return notVisited.isEmpty();
    }


    private void visit(Point next, Set<Point> notVisited, Set<Edge> toRemove) {
        if (!notVisited.remove(next))
            return;
        for (Point point : edges.get(next))
            if (!toRemove.contains(new Edge(next, point)) &&
                    !toRemove.contains(new Edge(point, next)))
                visit(point, notVisited, toRemove);
    }

    private void visitAndRemove(Set<Point> nodes, Point node) {
        if (nodes.contains(node)) {
            nodes.remove(node);
            List<Point> nextNodes = getEdges(node);
            for (Point next : nextNodes) {
                visitAndRemove(nodes, next);
            }
        }
    }
}


public class Edge {
    private final Point source;
    private final Point dest;

    public Edge(Point source, Point dest) {
        this.source = source;
        this.dest = dest;
    }

    @Override
    public boolean equals(Object o) {
        if (o == this || !(o instanceof Edge)) {
            return o == this;
        }

        Edge edge = (Edge) o;
        return Objects.equals(source, edge.source) &&
                Objects.equals(dest, edge.dest);
    }

    @Override
    public int hashCode() {
        return Objects.hash(source, dest);
    }
}

Я не уверен, почему мой метод isConnectedAfterRemoving() не работает. Как я могу это исправить? enter image description here

У меня также есть абстрактный класс Track и два подкласса NormalTrack и TrackSwitch.

  • TrackSwitch(int id, Point startPoint, Point endPoint, Point secondEndPoint, int length, boolean switchEnabled)
  • NormalTrack(int id, Point startPoint, Point endPoint, int length)

Как мне продолжить ..?

1 Ответ

0 голосов
/ 19 февраля 2020

Вы можете создать два класса NormalTrack и TrackSwitch и представлять каждый трек экземпляром этого класса. Классы хранят идентификатор, начальную точку и конечную (ые) точку (и) дорожки.

Тогда вы, вероятно, захотите сохранить для каждой точки список входящих дорожек, а также список исходящих дорожек. Переключатель немного сложен в этой настройке, поскольку он имеет две конечные точки. Возможно, вам также нужен флаг в коммутаторе, который сообщает, какая конечная точка активна в данный момент. Затем, когда вы перебираете входящие / исходящие треки точки и нажимаете TrackSwitch, вы должны сначала проверить, активна ли точка, которую вы перебираете, в данный момент. Если нет, то вы должны пропустить это.

...