Как создать матрицу смежности, используя входной текстовый файл, для представления ориентированного взвешенного графа [java]?
Мне трудно понять, как создать матрицу смежности из входного файла. Предполагается, что входной файл представляет собой ориентированный взвешенный граф узлов.
Цель состоит в том, чтобы создать программу, которая может выполнять итерационный поиск в глубину, но я действительно застрял в части ввода данных для ввода данных.
Входной текстовый файл предположительно будет выглядеть следующим образом:
каждый узел представлен двумя строками текста. Например, в самой верхней строке первая буква "S" - это имя узла, вторая буква "S" указывает, что это начальный узел, третья буква "n" означает, что это обычный узел, а не целевой узел, который будет обозначен как "г".
Во второй строке находятся два узла, соединенные с "S", первый из которых "B" с взвешенным расстоянием 1, а второй "E" с взвешенным расстоянием 2.
Третья строка должна быть пустой и шаблон повторяется.
S S n
B 1 E 2
B N n
C 2 F 3
C N n
D 2 GA 4
D N n
GA 1
E N n
B 1 F 3 H 6
F N n
I 3 GA
3 C 1
GA N g
H N n
I 2 GB 2 F 1
I N n
GA 2 GB 2
GB N g
Я действительно застрял на этом. Я использовал буферизованный ридер для сканирования в файле, но мне было интересно, будет ли проще использовать сканер.
В настоящее время я пытаюсь создать объекты Node с атрибутами, имеющими имя, и, возможно, ссылку на другие смежные объекты Node, используя какой-либо связанный список. Я также рассмотрел использование массива объектов узлов, но я действительно не уверен, как представить, какие узлы соединяются с какими другими узлами и как встроить это в матрицу смежности, используя двумерный массив.
Буду признателен за любые предложения, я новичок, поэтому я прошу прощения, если мой вопрос не имеет академического значения для других
Изменить: мой код выглядит примерно так: public void actionPerformed(ActionEvent e) {
if(e.getSource() == openButton)
{
returnVal = fileChooser.showOpenDialog(null);
if(returnVal == JFileChooser.APPROVE_OPTION)
{
selected_file = fileChooser.getSelectedFile();
String file_name = fileChooser.getSelectedFile().getName();
file_name = file_name.substring(0, file_name.indexOf('.'));
try
{
BufferedWriter buff_writer = null;
File newFile = new File("."+file_name+"_sorted.txt");
boolean verify_creation = newFile.createNewFile();
//if (verify_creation)
// System.out.println("file created successfully");
//else
// System.out.println("file already present in specified location");
file_reader1 = new BufferedReader(new FileReader(selected_file));
file_reader2 = new BufferedReader(new FileReader(selected_file));
FileWriter file_writer = new FileWriter(newFile.getAbsoluteFile());
buff_writer = new BufferedWriter(file_writer);
//find the number of nodes in the file
while( (currentLine = file_reader1.readLine()) != null)
{
k++;
System.out.println("value of k: " + k);
}
nodeArray = new Node[k];
while( (currentLine = file_reader2.readLine()) != null)
{
//System.out.print(currentLine);
String[] var = currentLine.split(" ");
nodeArray[x] = new Node(var[0], var[1], var[2]);
nodeArray[x].setLink1(new Node(var[3], null, null));
}
buff_writer.close();
file_writer.close();
}
catch (Exception e1)
{
e1.printStackTrace();
}
}
}
Редактировать № 2
мой нод объект выглядит примерно так:
public Node(String n, String t1, String t2)
{
name = n;
type1 = t1;
type2 = t2;
link1 = null;
link2 = null;
link3 = null;
link4 = null;
link5 = null;
link6 = null;
1 ответ
Дело в том, что вы не хотите использовать двумерный массив здесь. Вы хотите сделать шаг назад и спроектировать / смоделировать класс / структуру данных, которая соответствует "реальной проблеме", над которой вы работаете.
Другими словами: ваша проблема заключается в представлении графа узлов и ребер. Итак, несколько советов, чтобы вы начали..
Давайте начнем с:
enum NodeType { START, GOAL, NORMAL ; }
public class Node {
private final String name;
public Node(String name) {
this.name = name;
Выше приведен разумный способ различения разных типов узлов. И тогда мы начнем с представления узла. Очевидно, что его имя фиксировано - вы не хотите менять имя узла после того, как он был создан. Тогда у вас есть сеттеры, как
public void setType(NodeType type) ...
И больше полей,
private final Map<Node, Integer> neighbors = new HashMap<>();
и метод для добавления нового соседа:
public void addNeighborNode(Node node, int weight) {
neighbors.put(node, weight);
[для справки: теоретически вы можете создать класс, который принимает всю информацию через конструктор, избегая необходимости иметь методы установки. это имеет определенные преимущества, но усложняет ситуацию; и я думаю... то, что я показываю вам здесь, уже достаточно сложно;-) ]
Вся идея здесь - вы отделяете PARSING от того, как вы представляете / строите свои объекты. Конечно, в какой-то момент вы должны прочитать эти строки, чтобы затем построить из них объекты узлов.
Но лучше начать с класса Node, как описано выше, потому что тогда вы можете построить график... без необходимости разбора текстового файла:
Node n1 = new Node("n1");
n1.setType(NodeType.START);
Node n2 = new Node("n2");
n2.setType(NodeType.GOAL);
n1.setNeighborNode(n2, 5);
Другими словами: сначала вы строите хорошую "модель классов" для графа. И вы можете написать тестовый код, как указано выше. И когда все это работает; затем вы пишете код, который читает этот входной файл и переводит его в вызовы методов, которые вам нужны для построения вашего графика!
Короче говоря: разбор этого текстового файла важен, но не стоит на этом фокусироваться. Вместо этого: сначала подумайте о классовой модели ваших данных. То есть, где вы можете узнать больше всего и получить больше удовольствия от экспериментов. Потянув за ниточки и превратив их в предметы, это просто "работа". Повеселись сначала!