Union Find Datenstruktur

Kirby.exe

Top Contributor
Also wir sollen einen Minimum Spanning Tree erstellen mittels Kruskal Algorithmus. Hierzu soll ebenfalls die Union-Find Datenstruktur verwendet werden. Bei dieser Datenstruktur gibt es noch ein paar Unklarheiten.

Was genau passiert in dem MakeSet() und was passiert in Union() ?
 

Kirby.exe

Top Contributor
Ehrlich gesagt nicht wirklich :( Ich verstehe nicht was der Repräsentant sein soll. Ist das einfach das andere Ende der Kante oder was ist das?

Außerdem verstehe ich nicht wirklich was nun bei Union passiert, wird das Array erweitert oder wie? Wird der Eintrag einfach ersetzt? Oder wie wird dieser "neue" Repräsentant bestimmt?
 

LimDul

Top Contributor
Der Repräsentant ist einfach ein Element der Menge, was diese Menge identifiziert (Bei einer Menge mit einem Element ist es genau dieses eine Element)
Beispiel: Die Menge sind die Klassen einer Schule. Die Elemente der Menge sind die Schüler in der Klasse. Dann ist der Repräsentant einfach der "Klassensprecher" der Menge. Und wenn zwei Mengen M1 und M2 zusammengelegt werden, dann ist der neue Repräsentant einfach der Klassensprecher von M1.
 

Kirby.exe

Top Contributor
Also ich bin immer noch etwas verwirrt...xD Scheinbar ist das also eine Unterteilung in Sub Mengen welche per Referenz immer auf einen Kindes Knoten zeigen richtig? Was ich jedoch noch nicht verstanden habe ist, wie ich den einen gegebenen Knoten in diese Sub Mengen unterteile? Also nach welchen Kriterien?
 

LimDul

Top Contributor
Kritieren: Egal. Initial nimmt man einfach irgendein Element.
Wenn man mit komplett disjunkten Mengen startet (wie z.B. bei Kruskal, wo am Anfang jeder Knoten eine eigene Menge ist), dann ist der Knoten automatisch der Repräsentant.

Kruskal:
Angenommen du hast 10 Knoten v1 bis v10. Dann ist du initial folgende 10 Mengen (R = Repräsentant)

{ v1 } (R: v1)
{ v2 } (R: v2)
{ v3 } (R: v3)
{ v4 } (R: v4)
{ v5 } (R: v5)
{ v6 } (R: v6)
{ v7 } (R: v7)
{ v8 } (R: v8)
{ v9 } (R: v9)
{ v10 } (R: v10)

Dann läuft der Algorithmus los und will die Kante zwischen v1 und v5 aufnehmen.
find(v1) = v1 (Repräsentant von v1)
find(v5) = v5 (Repräsentant von v5)
=> Unterschiedlich, also unterschiedliche Teilbäume
Union(v1, v5) => { v1, v5} (R: v1}
Neue Mengen:
{ v1, v5 } (R: v1)
{ v2 } (R: v2)
{ v3 } (R: v3)
{ v4 } (R: v4)
{ v6 } (R: v6)
{ v7 } (R: v7)
{ v8 } (R: v8)
{ v9 } (R: v9)
{ v10 } (R: v10)
usw.

Als Datenstruktur wählt man da gerne Bäume, weil ein Union(M1, M2) einfach heißt "Hänge die Menge M2 unter einen Knoten der Menge M1.
 

Kirby.exe

Top Contributor
Ahhh ich verstehe :) Also ich nehme meine Kantenmenge und würde diese aufsteigend nach Gewicht sortieren. Danach würde ich dann mit der Datenstruktur anfangen und die Kanten der Reihenfolge nach linken oder? Als ergebnis sollte dann der Spanning Tree rauskommen?
 

LimDul

Top Contributor
Bei Kruskal ist die Union-Find Datenstruktur die Knoten-Menge. Die Kanten werden in einer simplen Datenstruktur gehalten, die einfach nach Kantengewicht sortiert ist.

Edit: Also ja, deine Aussage ist richtig (hatte sie zuerst falsch gelesen).
 

Kirby.exe

Top Contributor
Also ich habe jetzt meine grobe Union Find Datenstruktur, jedoch habe ich das Gefühl, dass ich falsch initialisiere... ich dachte, dass ich mit ein Elementigen Mengen anfange also ist der Repräsentant an Index i = i oder?

Hier ist meine Implementation:

Java:
public class UnionFind {
  
    int [] parents;
    int [] ranks;
  
    public UnionFind(int size) {
        parents = new int[size+1];
        ranks = new int[size+1];
    }
  
    public void union(int index1, int index2) {
        int temp1 = find(index1);
        int temp2 = find(index2);
      
        if(temp1 != temp2) link(temp1, temp2);
    }
  
    public void makeSet() {
        for(int i = 0; i < parents.length; i++) {
            parents[i] = i;
            ranks[i] = 0;
        }
    }
  
    private void link(int node1, int node2) {
        if (ranks[node1] > ranks[node2]) parents[node2] = node1;
        else {
            parents[node1] = node2;
            if (ranks[node1] == ranks[node2]) ranks[node2]++;
        }
    }
  
    private int find(int index) {
        return parents[index];
    }
  
    public int[] getTree() {
        return parents;
    }
}
 
Zuletzt bearbeitet:

Kirby.exe

Top Contributor
Oder vielleicht anders:

Ich bin immernoch etwas verwirrt...Den ich erkenne an dem Ergebnis nicht so wirklich einen Spanning Tree da zwar 6 von 6 Elementen in einer Menge sind (also den gleichen Repräsentanten haben) aber ich erkenne keine Struktur oder Hierarchie :(
 

LimDul

Top Contributor
Naja, du musst dir auch die Kanten merken, die dazu geführt haben, das ein Knoten hinzugefügt wurde. Diese Kanten sind die Kanten des Minimum Spanning Trees
 

Kirby.exe

Top Contributor
Naja, du musst dir auch die Kanten merken, die dazu geführt haben, das ein Knoten hinzugefügt wurde. Diese Kanten sind die Kanten des Minimum Spanning Trees
Naja das tue ich hier:

Java:
public void runOp() {
        ArrayList<GraphNode> spanningTree = new ArrayList<>();
        ArrayList<GraphNode> unusedNodes = graph.getAllNodes();
        ArrayList<Integer> usedNodes = new ArrayList<>();
        UnionFind s = new UnionFind(graph.numberOfNodes);
       
        Collections.sort(unusedNodes);
       
        while(!unusedNodes.isEmpty()) {
            GraphNode current = unusedNodes.remove(0);
            if(s.find(current.startNode) != s.find(current.endNode)) {
                spanningTree.add(current);
                s.link(s.find(current.startNode), s.find(current.endNode));
            }
           
        }
       
        this.printSpanningTree(spanningTree);
    }

Es läuft aber ewig und ein Freund von mir hat gesagt, dass wenn man es richtig man es eigentlich nur 1-2 Sec dauern sollte...xD
 

LimDul

Top Contributor
Ich verstehe den Code nicht- Wo ist die Liste der Kanten und wo der Knoten? Du musst über die Liste der Kanten iterieren und die Union-Datenstruktur über die Liste der Knoten führen. Warum hat bei dir ein GraphNode einen Start und ein Ende?
 

Kirby.exe

Top Contributor
Oh das war eine scheiß bennenung meinerseits...GraphNode sollte GraphArc sein xD Das sind die Kanten, deswegen Start und endKnoten :)

UnusedNodes sollte unusedArcs heißen :)
 

LimDul

Top Contributor
Wenn deine Union Datenstruktur nur noch eine Menge enthält solltest du auch abbrechen. Es ist ziemlich witzlos, dann die ganzen restlichen Kanten zu prüfen.
 

LimDul

Top Contributor
Wenn deine UnionFind Datenstrtuktur nur noch aus einer Menge besteht. Keine Ahnung was es da an Methoden gibt, size() == 1 wäre ein Möglichkeit.
 

Kirby.exe

Top Contributor
ja gut xD Ich reduziere das Array in dem Sinne nicht xD Also müsste ich hier mit einer Schleife über das Array laufen und schauen ob alle den gleichen Repräsentanten haben xD zumindest fällt mir spontan nichts effizienteres ein :)
 

Kirby.exe

Top Contributor
Update:

Ich habe es hinbekommen, dass die Laufzeit schnell ist (Einfach auf ArrayList verzichtet und only Arrays verwendet :) )

Das Problem ist nun, das die Costen des Spanning Trees (also alle Weg Gewichte addiert) nicht korrekt berechnet werden...Ich habe alles überprüft:

Bin mir ziemlich sicher, dass die Union Find Datenstruktur richtig ist, der Kruskal Algorithmus ist exakt so vom Wikipedia Pseudo Code implementiert (außer das der Vergleich es die gleiche Submenge ist, das passiert intern in union) und sonst wüsste ich nicht woran es liegen kann.

Hier sind die Dateien:

Java:
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;

public class Kruskal {

    private Graph graph;
    private double timeForTest = 0.0;

    public long runOp() {
        GraphArc [] arcs = new GraphArc[graph.numberOfArcs];
        arcs = graph.getArray();

        UnionFind s = new UnionFind(graph.numberOfNodes);

        Arrays.sort(arcs);

        long wayCost = 0;

        for(int i = 0; i < arcs.length; i++) {

            GraphArc current = arcs[i];
           
            if(s.union(current.startNode, current.endNode)) {
                wayCost += current.weight;
            }
        }
        return wayCost;
    }

    public void readGraph(String filename) {
        try {
            BufferedReader in = new BufferedReader(new FileReader(filename));
            String line = "";
            String[] parts = null;

            while((line = in.readLine()) != null) {
                //System.out.println("Current Line: " + line);
                if(line.charAt(0) == 'c') {
                }else if(line.charAt(0) == 'p') {
                    parts = line.split(" ");
                    graph = new Graph(convertInt(parts[2]), convertInt(parts[3]));
                }else if(line.charAt(0) == 'a') {
                    parts = line.split(" ");
                    //System.out.println(Arrays.toString(parts));
                    int start = convertInt(parts[1]);
                    int end = convertInt(parts[2]);
                    int weightNode = convertInt(parts[3]);
                    graph.add(start, end, weightNode);
                    //System.out.println(graph.toString());
                }else {
                    System.out.println("This Character is not valid!!!");
                }
            }
            //System.out.println(graph.toString());
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    private int convertInt(String input) {
        return Integer.parseInt(input);
    }

}
Java:
public class UnionFind {
   
    private int[] parents;
    private int[] rank;
   
    public UnionFind(int numberOfNodes) {
        parents = new int[numberOfNodes+1];
        rank = new int[numberOfNodes+1];
       
        this.makeSet();
    }
   
    private void makeSet() {
        for(int i = 0; i < parents.length; i++) {
            parents[i] = i;
            rank[i] = 0;
        }
    }
   
    public boolean union(int value1, int value2) {
        int temp1 = find(value1);
        int temp2 = find(value2);
       
        if(temp1 != temp2) {
            link(temp1, temp2);
            return true;
        }
        return false;
    }
   
    private void link(int value1, int value2) {

        if (rank[value1] < rank[value2])
            parents[value1] = value2;
        else if (rank[value2] < rank[value1])
            parents[value2] = value1;
        else {
            parents[value1] = value2;
            rank[value2] += 1;
        }
    }
   
    private int find(int value) {
        return parents[value];
    }
}
Java:
import java.util.ArrayList;

public class Graph {
   
    private ArrayList<ArrayList<GraphArc>> adjazenzlist;
    private GraphArc[] arcs;
    private int counter;
    public int numberOfNodes;
    public int numberOfArcs;

    public Graph(int numberOfNodes, int numberOfPaths) {
        adjazenzlist = new ArrayList<ArrayList<GraphArc>>();
        arcs = new GraphArc[numberOfPaths];
        counter = 0;
        this.numberOfNodes = numberOfNodes;
        this.numberOfArcs = numberOfPaths;
       
        for(int i = 0; i < numberOfNodes+1; i++) {
            adjazenzlist.add(new ArrayList<GraphArc>());
        }
    }
   
    public void add(int startNode, int endNode, int weight) {
        adjazenzlist.get(startNode).add(new GraphArc(startNode, endNode, weight));
        arcs[counter] = new GraphArc(startNode, endNode, weight);
        counter++;
    }
   
    public GraphArc[] getArray() {
        return arcs;
    }
   
    public String toString() {
        StringBuilder sb = new StringBuilder();
        for(int i = 0; i < adjazenzlist.size(); i++) {
            if(adjazenzlist.get(i).size() == 0) continue;
            sb.append(i + ": ");
            for(int j = 0; j < adjazenzlist.get(i).size(); j++) {
                GraphArc s = adjazenzlist.get(i).get(j);
                sb.append("(" + i + ", " + s.endNode + ", " + s.weight + ")");
                if(j != adjazenzlist.get(i).size() - 1) {
                    sb.append(", ");
                }
            }
            sb.append("\n");
        }
        return sb.toString();
    }
   
}
Java:
public class GraphArc implements Comparable<GraphArc>{
   
    public int startNode;
    public int endNode;
    public int weight;
   
    public GraphArc(int startNode, int endNode, int weight) {
        this.startNode = startNode;
        this.endNode = endNode;
        this.weight = weight;
    }

    @Override
    public int compareTo(GraphArc o) {
       
        if(o.weight > this.weight) return -1;
        else if(o.weight == this.weight) return 0;
        else return 1;
    }
   
    public String toString() {
        return "(" + this.startNode + ", " + this.endNode + ", " + this.weight + ")";
    }
}

Hier ist mein geschriebener JUnit Test:
Java:
import static org.junit.jupiter.api.Assertions.assertEquals;

import org.junit.jupiter.api.Test;

public class KruskalTest {
   
    @Test
    public void kruskalLastTest() {
       
        Kruskal s = new Kruskal();
        String directory = "/Users/userNameHere/Desktop/instances/";
       
        s.readGraph(directory + "USA-road-d.NY.gr");
        long result = s.runOp();
        assertEquals(261159288, result, "Got " + result + " but expected 261159288!");
        System.out.println("OK!");
       
        s.readGraph(directory + "USA-road-d.BAY.gr");
        result = s.runOp();
        assertEquals(435798417, result, "Got " + result + " but expected 435798417!");
        System.out.println("OK!");
       
        s.readGraph(directory + "USA-road-d.COL.gr");
        result = s.runOp();
        assertEquals(1323900090, result, "Got " + result + " but expected 1323900090!");
        System.out.println("OK!");
       
        s.readGraph(directory + "USA-road-d.FLA.gr");
        result = s.runOp();
        assertEquals(1806814846, result, "Got " + result + " but expected 1806814846!");
        System.out.println("OK!");
       
        s.readGraph(directory + "USA-road-d.NW.gr");
        result = s.runOp();
        assertEquals(3522586810L, result, "Got " + result + " but expected 3522586810!");
        System.out.println("OK!");
       
        s.readGraph(directory + "USA-road-d.NE.gr");
        result = s.runOp();
        assertEquals(2131122758L, result, "Got " + result + " but expected 2131122758!");
        System.out.println("OK!");
       
    }

}

Hier sind die Test Instanzen:
 

LimDul

Top Contributor
Aus dem Bauch heraus - ohne genauer reinzuschauen - sieht mir das link nicht korrekt aus.

Sobald die Vereinigung von zwei Mengen aus mehr als zwei Elementen steht, müsste eigentlich der parent von allen Element aktualisiert werden. Und der Rank ist komplett überflüssig in der Implementierung, der macht aktuell einfach gar nichts.

Mach mal einen Test auf die Union find Struktur mit 4 Elementen und mach dann ein union(1,2) und (2,3) und dann noch mal ein Union(1,3) und Union(1,2) und Union(2,3), die sollten ja alle false liefern. Ich wette einer der drei Aufrufe liefert true.
 

Kirby.exe

Top Contributor
Yep du hattest recht, bei insgesamt 4 Elementen funktioniert alles richtig, aber ab 8 Elementen nicht mehr, da sind unions true obwohl diese Mengen bereits gemerged wurden :) Aber wie fixe ich das....xD Soll ich bei jedem link() dann über das Array iterieren und alle mit diesem Parent gegen den neuen replacen? Dann hätte die Methode ja eine Laufzeit von O(n) oder ist das nicht so schlimm?
 

Kirby.exe

Top Contributor
Also der JUnit Test sagt schonmal dass es das richtige Ergebnis liefert :)

Habe die Methode so:

Java:
private void link(int value1, int value2) {
        int searchValue = 0;
        int replaceValue = value2;
        
        if (rank[value1] < rank[value2]) {
            searchValue = value1;
            replaceValue = value2;
            parents[value1] = value2;
        }else if (rank[value2] < rank[value1]) {
            searchValue = value2;
            replaceValue = value1;
        }else {
            searchValue = value1;
            replaceValue = value2;
        }
        
        for(int i = 0; i < parents.length; i++) {
                if(parents[i] == searchValue) {
                    parents[i] = replaceValue;
                    rank[replaceValue]++;
                }
         }
    }

Aber wie die schon gesagt hast müsste ich jetzt schauen wie ich das am besten implementiere :) Danke für deine Hilfe :) Jetzt weiß ich zumindest wo ich ansetzen muss :)
 

Kirby.exe

Top Contributor
Habe es gelöst :) Habe im Skript gelesen, dass die Find Methode beim suchen automatisch eine Pfadkompression durchführen soll und da ja Array Zugriffe in O(1) passieren ist das tausend mal schneller als in O(n) über das Array zu iterieren :)

Mal ne Off-Topic Frage:

Werden Union-Find Datenstrukturen auch in Navigationssystemen verwendet oder funktionieren die komplett anders?
 

LimDul

Top Contributor
Ich wüsste nicht, was die da bringen, weil ein Algorithmus wie A* oder Dijsktra braucht die, soweit ich gerade weiß, nicht. Das ist ja eine Mengenbasierte Datenstruktur - bei Navigation interessieren mich Pfade und keine Mengen.
 

Kirby.exe

Top Contributor
Ich wüsste nicht, was die da bringen, weil ein Algorithmus wie A* oder Dijsktra braucht die, soweit ich gerade weiß, nicht. Das ist ja eine Mengenbasierte Datenstruktur - bei Navigation interessieren mich Pfade und keine Mengen.
Ach stimmt xD Da habe ich mich verwirrt xD Ich meinte etwas anderes xD Mir hat mal jemand erzählt das wohl in Netwerken wenn man nicht nur static routing sondern auch einen DHCP Part hat, das irgendwie da Minimum Spanning Tree verwendet wird oder so xD Oder hat ich das auch falsch im Gedächtnis?o_O
 

LimDul

Top Contributor
Da klingelt bei mir auch was, google sagt: https://de.wikipedia.org/wiki/Spanning_Tree_Protocol

Damit hört mein Wissen da aber auch schon auf. Ob da wirklich diese Datenstrukturen verwendet werden, keine Ahnung. Sehe ich aber gefühlt skeptisch, da:
* Die Graph-Größe vermutlich relativ klein sein sollte
* Da auch alternative Wege und Co betrachtet werden müssen in den Protokollen, eine reine Union-Find Struktur vermutlich nicht reicht

Aber das Teilaspekte davon in Implementierungen verwendet werden, halte ich nicht für ausgeschlossen.
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
D Union in einem Struct in JNA Allgemeine Java-Themen 5
D Selenium - cannot find Chrome binary Allgemeine Java-Themen 6
bueseb84 Java : Cannot find Symbol Allgemeine Java-Themen 7
C Compiler-Fehler Cannot find symbol bei Hat-Beziehungen Allgemeine Java-Themen 5
P Find Bugs plugin Allgemeine Java-Themen 2
P JDK installieren Error: Could not find or load main class HelloWorld.java Allgemeine Java-Themen 3
C JNI loadLibary "Can't find dependent libraries" Allgemeine Java-Themen 2
S String mit Matcher.find durchsuchen und ausgeben Allgemeine Java-Themen 7
Phash Can't find Main Class Allgemeine Java-Themen 4
N Runtime.getRuntime().exec Problem mit find Allgemeine Java-Themen 3
S lp_solve mit Java nutzen - Can't find dependent libraries Allgemeine Java-Themen 8
127.0.0.1 Methodenaufruf -cannot find symbol- Allgemeine Java-Themen 14
X Could not find the main class programm will exit (textdokument) Allgemeine Java-Themen 3
S Could not find the main class Allgemeine Java-Themen 7
B Mal wieder "Could not find the main class" Allgemeine Java-Themen 3
C Could not find the main class. Allgemeine Java-Themen 15
nrg Find and replace Text docx Allgemeine Java-Themen 6
A Could not find main class: start Allgemeine Java-Themen 5
hdi Could not find main class? Allgemeine Java-Themen 8
B Cannot find main-claas... Allgemeine Java-Themen 21
P Java Editor Could not find the main class GUI. Programm will exit. Allgemeine Java-Themen 3
Tobse Cannot find symbol : construktor --- Deklariert! Allgemeine Java-Themen 9
D 'InputStreamReader' & 'BufferedReader' führen zu "cannot find symbol"-Fehler Allgemeine Java-Themen 3
BattleMaster246 Could not find the Main class Allgemeine Java-Themen 30
N Probleme mit .jar 'Could not find main class' Allgemeine Java-Themen 3
B cannot find Symbol Allgemeine Java-Themen 2
borobudur Find a AWT frame in SWT Allgemeine Java-Themen 4
A Problem mit StringBuilder delete - find den Fehler nicht Allgemeine Java-Themen 9
N Eclipse 3.4(Ganymede) "find references in workspace&quo Allgemeine Java-Themen 4
V JNI Can't find dependent libraries Allgemeine Java-Themen 4
G "Could not find the main class. Program will exit" Allgemeine Java-Themen 20
R Ausführen von *.JAR || "Could not find main class" Allgemeine Java-Themen 7
I "Could not find the main class. Program will exit" Allgemeine Java-Themen 6
B Could not find the main class Allgemeine Java-Themen 2
M Eigene Datenstruktur um eine Menge zu speichern Allgemeine Java-Themen 3
U Klassen Komplexe Datenstruktur in Java Allgemeine Java-Themen 4
J Datenstruktur für eine Map erstellen Allgemeine Java-Themen 2
B Suche geeignete Datenstruktur Allgemeine Java-Themen 5
ruutaiokwu datenstruktur welche sich "im kreis" dreht Allgemeine Java-Themen 26
P Große Datenstruktur im Speicher halten Allgemeine Java-Themen 13
B Suche passende Datenstruktur für 2 Einträge Allgemeine Java-Themen 19
G Welche Datenstruktur? Allgemeine Java-Themen 19
R Collections Datenstruktur gesucht Allgemeine Java-Themen 12
D Datenstruktur für Hierarchie/Baum mit Tiefe 3 Allgemeine Java-Themen 8
D Datenstruktur .. BlockingQueue (LIFO) Allgemeine Java-Themen 3
P Suche Datenstruktur Allgemeine Java-Themen 2
S Welche Datenstruktur für verschiedene Sprachen sinnvoll? Allgemeine Java-Themen 2
ruutaiokwu schnelle datenstruktur... Allgemeine Java-Themen 13
S Baumstruktur/Datenstruktur in Datei speichern Allgemeine Java-Themen 23
D Datenstruktur Allgemeine Java-Themen 2
B Datenstruktur: Liste Allgemeine Java-Themen 5
A Thread sichere Datenstruktur Allgemeine Java-Themen 5
J Arrayähnliche Datenstruktur Allgemeine Java-Themen 4
B Script Problem "Dynamische Datenstruktur" Allgemeine Java-Themen 13
S Frage zum Design der Datenstruktur Allgemeine Java-Themen 10
G Datenstruktur: LISTEN Allgemeine Java-Themen 7
D Suche nach passender Datenstruktur Allgemeine Java-Themen 4
N Datenstruktur für Netze gesucht Allgemeine Java-Themen 8
G Daten von Excel kopieren - sinnvolle Datenstruktur? Allgemeine Java-Themen 3
U eigene Datenstruktur ArrayList<String> nach Object [][ Allgemeine Java-Themen 2
F welche Datenstruktur? Allgemeine Java-Themen 9
F Welche Datenstruktur Allgemeine Java-Themen 2
T Datenstruktur gesucht Allgemeine Java-Themen 18
T Datenstruktur für großes Netz Allgemeine Java-Themen 2
Z Welche Datenstruktur verwende ich h_ier bloss ? Allgemeine Java-Themen 14
G NullPointer. in einer Datenstruktur Allgemeine Java-Themen 2
S Welche Datenstruktur passt bei mir? Allgemeine Java-Themen 6
H Speicheverbrauch einer Datenstruktur ermitteln Allgemeine Java-Themen 29
S Suche geeignete Datenstruktur Allgemeine Java-Themen 27
S Datenstruktur für einen Baum Allgemeine Java-Themen 5
D Welche Datenstruktur? Allgemeine Java-Themen 2
T Datenstruktur für Straße ! Allgemeine Java-Themen 5
B Datenstruktur elegant zerlegen Allgemeine Java-Themen 6
G Datenstruktur gesucht: Allgemeine Java-Themen 3
A Datenstruktur und Sortierung Allgemeine Java-Themen 12

Ähnliche Java Themen

Neue Themen


Oben