Java - Komponenten aus einem Graph berechnen / Algorithmus?
Hallo, ich arbeite gerade an einem Graphenprogramm und der nächste Schritt ist es ,mir die Zusammenhangskomponenten des Graphes auslesen zu lassen.
Eine dafür notwendige Wegmatrix habe ich schon programmiert:
public void berechneKomponenten()
{
for (int i = 0; i < Matrix.length; i++)
{
for(int j = 0; j < Matrix[i].length; j++)
{
if(WegMatrix[i][j] == 1)
{
int buchstabe_int = i+65;
char buchstabe_char = (char) buchstabe_int;
System.out.print(buchstabe_char + ",");
}
}
}
}
Die Ausgabe sieht so aus:
A, A, A, B, B, C, C, C, D, D, D, E, E
--------------------------------------------------------
Und das ist im Prinzip auch richtig, denn:
Die Buchstaben (A-E) habe ich zum Verständnis hinzugefügt.
-------------------------------------------------------------------------------------
Meine Wegmatrix hat:
- 3 A's
- 2 B's
- 3 C's
- 3 D's
- 2 E's
Verglichen mit meiner Ausgabe:
A, A, A => 3 A's
B, B => 2 B's
C, C, C => 3 C's
D, D, D = > 3 D's
E, E => 2 E's
-----------------------------------
Doch die Ausgabe sollte so aussehen: (Siehe K1 und K2)
bzw so:
Wie schaffe ich das?
Danke!
2 Antworten
Hab leider noch nie mit Wegematrizen gearbeitet, aber für mich sieht es so aus, als müsste man für die Menge der beteiligten Knoten einer Komponente einfach die Spalten für jede Zeile durchgehen und schauen wo eine 1 steht. Diese Knoten fügt man dann einer Menge hinzu. Und dann muss man halt noch darauf achten, dass es nicht mehrere gleiche Komponenten geben kann, also pro Zeile schauen, ob es diese Komponente schon gibt.
Ich bin mir aber nicht sicher, ob man aus der Wegematrix ablesen kann, dass (in deinem Beispiel jetzt) nur Kanten zwischen (1,3) und (1,4) existieren.
Soweit ich es verstanden hab, gibt die Wegmatrix an, ob man von einem Knoten irgendwie, also nicht nur auf direktem Weg zum anderen Knoten kommen kann.
Ich denke die Adjazenzmatrix könnte da helfen die direkten Kanten zwischen den Knoten bzw. die Knoten mit einer direkten Kante innerhalb einer Komponente zu bestimmen.
Hab das mal als Programm implementiert, so wie ich denke, dass du es haben möchtest, vielleicht hilft dir das ja irgendwie.
Graph.java
import java.util.ArrayList;
class Graph {
public Graph() {
// die Wegematrix
int[][] wegeMatrix = {
{1,0,1,1,0},
{0,1,0,0,1},
{1,0,1,1,0},
{1,0,1,1,0},
{0,1,0,0,1}};
// berechne Komponenten
ArrayList<Komponent> komponenten = berechneKomponenten(wegeMatrix);
// Gebe Komponenten aus
for(int i=0;i<komponenten.size();i++) {
System.out.println("Komponente "+i +": "+komponenten.get(i));
}
}
// Methode zum Berechnen der Komponenten
public ArrayList<Komponent> berechneKomponenten(int[][] w) {
// initialisiere eine Liste von Komponenten
ArrayList<Komponent> komponenten = new ArrayList();
for(int zeile=0;zeile<w.length;zeile++) {
// erstelle eine Komponente pro Zeile
Komponent k = new Komponent();
for (int spalte=0;spalte<w[0].length;spalte++) {
if(w[zeile][spalte] == 1) {
// wenn in der Wegematrix eine 1, dann speichere
// eine Node in der aktuellen Komponente mit
// jeweiligem Char und index
int index = spalte;
Node n = new Node((char)(spalte+65), index);
k.addNode(n);
}
}
// Sofern die Komponente nicht in der Liste
// existiert, füge sie hinzu
if(!komponenten.contains(k)){
komponenten.add(k);
}
}
// vollständige Liste der Komponenten zurückgeben
return komponenten;
}
}
Node.java
class Node {
protected char c;
protected int index;
public Node(char c, int index) {
this.c = c;
this.index = index;
}
public String toString() {
return ""+(index+1);
}
public boolean equals(Object other) {
if(!(other instanceof Node)) return false;
return ((Node)other).c == this.c;
}
public int hash(){
return (int) this.c;
}
}
Komponent.java
import java.util.ArrayList;
class Komponent {
protected ArrayList<Node> nodes = new ArrayList();
public void addNode(Node n) {
if(!nodes.contains(n)){
nodes.add(n);
}
}
public boolean equals(Object other) {
if(!(other instanceof Komponent)) return false;
Komponent k = (Komponent) other;
if(k.nodes.size() != this.nodes.size()){
return false;
}else {
for (int i=0; i<this.nodes.size(); i++) {
if(!(this.nodes.get(i).equals(k.nodes.get(i)))) return false;
}
}
return true;
}
public int hash(){
int i = 0;
for(int k=0;k<nodes.size();k++){
i+= Math.pow(2,(int) (nodes.get(k).c));
}
return i;
}
public String toString() {
String r = "{";
for(int i=0;i<this.nodes.size();i++) {
Node n = this.nodes.get(i);
if(i==this.nodes.size()-1) {
r += n.toString()+"";
}else {
r += n.toString()+",";
}
}
return r+"}";
}
}
Ich habe mal Binärbaumen als Code realisiert..und ich glaube, dass es eine ähnliche herangehensweise ist. Also wenn du es mit einer Matrix machen willst, kannst du einfach wie @Smirror beschrieben machen...in Java kann man ja einfach Matrizen anlegen.
Zu den Knoten, würde ich eine eigene Klassen Implementieren (nodes).