Variable zurücksetzen (Java)?

2 Antworten

Vom Fragesteller als hilfreich ausgezeichnet

Hallo Dieter,

ich versuche mal möglichst wenig zu ändern:

package algorithmen;

class Node {
    private String data;
    private Node child = null;

    public Node(String data){
        this(data, null);
    }

    public Node(String data, Node child) {
        this.data = data;
        this.child = child;
    }

    public void addChild(Node node) {
        if (this.child == null) {
            this.child = node;
        } else {
            this.child.addChild(node);
        }
    }

    public void printChildren(Node node) {
        int i = 0;
        Node child = node.getChild();

        while (child != null) {
            System.out.println("\t"+child.getData());
            child = child.getChild();
            i++;
        }
        System.out.printf("Anzahl Kindern und Kindeskindern: %d\n", i);
    }

    public void printNextGeneration(Node node) {
        Node child = node.getChild();
        while (child != null) {
            System.out.println("\t"+child.getData());
            child = child.getChild();
        }
    }

    public static void main(String[] args) {
        Node root = new Node("1");
        root.addChild(new Node("1. Kind von 1"));
        root.addChild(new Node("2. Kind von 1"));
        root.addChild(new Node("3. Kind von 1"));
        root.addChild(new Node("4. Kind von 1"));

        root.getChild().addChild(new Node("Kind von 1.Kind von 1"));

        System.out.println("Methode Kinder");
        root.printChildren(root);

        System.out.println("Methode zeige naechste Generation");
        root.printNextGeneration(root);
    }

    private String getData() {
        return this.data;
    }

    private Node getChild() {
        return this.child;
    }
}

Zunächst mal habe ich die Klasse Child entfernt, da diese nichts tut, was nicht auch die Klasse Node schon tun würde. Nodes sind Kinder, wenn sie Nodes als Eltern haben. Du brauchst keine extra Klasse "Kind".

Dann habe ich alle Member der Klasse Node private gemacht. Somit kann ich auch nicht "versehentlich" die Member manipulieren so wie Du das gemachst hast.

Ich bin bei deiner Implementierung nicht sicher ob ein Node nicht beliebig viele Kinder haben kann. Es sieht etwas so aus. Wenn Du das erreichen möchtest, dann musst Du mit Listen, Arrays, oder ähnlichen Strukturen arbeiten. Bei der aktuellen Implementierung hat jeder Node maximal ein Kind. Dieses Kind kann selbst wieder maximal ein Kind besitzen.

Bei der Iteration, also wenn ich die Kinder und Kindeskinder ausgebe, verwende ich nun jeweils eine Hilfsvariable

Node child = node.getChild();

Damit verändere ich die Kinder nicht mehr so wie Du das zuvor gemacht hast. Es wäre mir nicht mal möglich, da ich die Member privat gemacht habe. Selbstverständlich könnte ich noch die addChild Methode aufrufen, aber diese sorgt dafür, dass ich keine Kinder überschreiben kann.

Um es ganz klar zu sagen, dein Problem ist das hier:

node.children=node.children.next;

children ist ein öffentliches Member von Node und Du überschreibst dieses Member mit dem Nachfolger von children. Das machst Du einmal für alle Kinder/Kindeskinder und damit ist die Struktur dann hin.

Gruß

Woher ich das weiß:Berufserfahrung

Dieter987 
Fragesteller
 24.12.2019, 14:40

Vielen Dank! Ja, die Anzahl der Kinder ist beliebig da muss ich dann einmal sehen wie ich das am besten mache.

0
AldoradoXYZ  24.12.2019, 15:15
@Dieter987

Hallo Dieter,

ich haber hier mal ein Beispiel mit Listen gebaut. Ich vermute mal, dass Du Streams noch nicht gelernt hast, aber die sind einfach zu schön, darum habe ich sie benutzt.

Außerdem habe ic noch ein parent hinzugefügt, weil ich gerne eine Einrückung nach Anzahl der Elterngenerationen haben möchte.

Insgesamt kann man sicherlich noch eine Menge optimieren, aber für den Start schon brauchbar.

package algorithmen;

import com.google.inject.internal.util.ImmutableList;

import java.util.LinkedList;
import java.util.List;

class Node {
    private String data;
    private List<Node> children = new LinkedList<>();
    private Node parent = null;

    public Node(String data) {
        this(data, null);
    }

    public Node(String data, Node child) {
        this.data = data;
        if (child != null) {
            this.children.add(child);
        }
    }

    public void addChild(Node node) {
        node.setParent(this);
        this.children.add(node);
    }

    public void printChildren() {
        List<Node> children = getChildren();
        children.forEach(Node::printNode);
    }

    public void printNode() {
        int ancestorCount = this.getAncestorCount();
        while (ancestorCount>0){
            System.out.print("\t");
            ancestorCount--;
        }
        System.out.println(this.getData());
    }

    public void printNextGeneration() {
        List<Node> children = this.getChildren();

        children.stream()
                .peek(Node::printChildren)
                .forEach(Node::printNextGeneration);
    }

    public static void main(String[] args) {
        Node root = new Node("1");
        Node firstChild = new Node("1. Kind von 1");
        root.addChild(firstChild);
        root.addChild(new Node("2. Kind von 1"));
        root.addChild(new Node("3. Kind von 1"));
        root.addChild(new Node("4. Kind von 1"));

        Node childOfChild = new Node("Kind von 1.Kind von 1");
        firstChild.addChild(childOfChild);

        Node grandChild = new Node("Enkelkind von 1");
        childOfChild.addChild(grandChild);

        Node greatGrandChild = new Node("Urenkelkind von 1");
        grandChild.addChild(greatGrandChild);

        System.out.println("Methode Kinder");
        root.printChildren();
        System.out.printf("Anzahl Kindern: %d\n", root.getChildCount());

        System.out.println("Methode zeige naechste Generationen");
        root.printNextGeneration();
    }

    private String getData() {
        return this.data;
    }

    private List<Node> getChildren() {
        return ImmutableList.copyOf(this.children);
    }

    private int getChildCount() {
        return children.size();
    }

    private void setParent(Node parent) {
        this.parent = parent;
    }

    private Node getParent() {
        return parent;
    }

    private int getAncestorCount() {
        Node parent = getParent();
        int ancestorCount =0;
        while (parent!=null){
            ancestorCount++;
            parent = parent.getParent();
        }

        return ancestorCount;
    }
}

Ausgabe:

Methode Kinder
	1. Kind von 1
	2. Kind von 1
	3. Kind von 1
	4. Kind von 1
Anzahl Kindern: 4
Methode zeige naechste Generationen
		Kind von 1.Kind von 1
			Enkelkind von 1
				Urenkelkind von 1

printChildren gibt nun nur noch die direkten Kinder aus und wird von printNextGeneration benutzt. printNextGeneration geht nun in die Tiefe und gibt alle Generationen aus.

Die addChild Methode ist nun etwas interessanter, denn sie setzt mit

node.setParent(this);

gleich die richtige Eltern-Kind Beziehung. So kann man gar nicht erst vergessen den parent korrekt zu setzen.

printNode ist nur dafür Zuständig eine Ausgabe zu erzeugen und macht dabei die gewünschte Einrückung nach Anzahl der Vorfahren. Da müsste man dann überlegen ob man das bei einem printNode wirklich will, oder ob das nicht eher in die printNextGeneration gehört.

Gruß und viel Spaß, evtl. bringt es dich ja auf Ideen.

0
AldoradoXYZ  24.12.2019, 15:24
@Dieter987

Wenn Du mir sagst welche Datenstruktren Du kennst, dann könnte ich damit eine Lösung implementieren.

Arrays vielleicht? Vectoren?

Irgendetwas um mehrere Referenzen aufzunehmen.

Gruß

0
Dieter987 
Fragesteller
 24.12.2019, 15:37
@AldoradoXYZ

Wissen Sie, eigentlich muss ich eine Aufgabe in ABAP umsetzen, es soll ein "Weihnachtsbaum" generiert werden. Bei dem durch Benutzereingabe von Tiefe des Baumes und Anzahl der maximalen Knoten ein entsprechender Baum generiert wird. Zunächst wollte ich die Datenstruktur in Java realisieren um erstmal eine Grundlage zu haben.

Die Anzahl der Kinder muss am Ende zufällig für jeden Elternknoten erzeugt werden. Ist dies mit Arrays möglich in Java? Kenne mich mit Java nicht aus, habe bis jetzt eher viel in C gemacht, da ABAP aber auch objektorientiert ist wollte ich es erstmal in Java umsetzen.

Wenn eine entsprechende Lösung für Arrays möglich ist bezüglich der zufälligen Anzahl dann würde ich mich darüber freuen.

0
AldoradoXYZ  24.12.2019, 16:37
@Dieter987

Mit Arrays funktioniert das natürlich auch.

Dabei ist etwas schade, dass man eine dynamisch erweiterbare Struktur implementiert, nämlich den Baum, und dann auf eine statische Struktur wie einem Array zurückgreifen soll. Eine dynamisch verkettete Liste (Nodes mit Kind-Nodes) wäre viel sinnvoller.

Greift man auf Arrays zurück, dann muss man das Array unweigerlich irgendwann in ein größeres Array kopieren. Ich implementiere das hier so, dass ich bei einem neuen Child ein komplett neues Array erzeuge welches genau ein Element mehr fasst. Dann kopiere ich das alte Array in das neue Array und referenziere das neue Element an der letzten Stelle des Arrays. Für die Aufgabe sicherlich völlig ausreichend. Wenn man effizienter sein möchte, dann erweitert man das Array gleich um mehrere Elemente und merkt sich, welcher Index der zuletzt benutzte war. Beliebt ist hier die Array-Größe zu verdoppeln. Wenn man solchen Aufwand betreibt, dann kann man aber auch gleich über eine verkettete Liste nachdenken.

package algorithmen;

import java.util.Arrays;

class Node {
    private String data;
    private Node[] children = new Node[0];
    private Node parent = null;

    public Node(String data) {
        this(data, null);
    }

    public Node(String data, Node child) {
        this.data = data;
        if (child != null) {
            this.addChild(child);
        }
    }

    public void addChild(Node node) {
        node.setParent(this);
        
        Node[] newChildren = copyArrayWithOneExtra(children);
        newChildren[newChildren.length - 1] = node;

        this.children = newChildren;
    }

    public void printChildren() {
        Node[] children = getChildren();

        Arrays.stream(children)
                .forEach(Node::printNode);
    }

    public void printNode() {
        int ancestorCount = this.getAncestorCount();
        while (ancestorCount > 0) {
            System.out.print("\t");
            ancestorCount--;
        }
        System.out.println(this.getData());
    }

    public void printNextGeneration() {
        Arrays.stream(children)
                .peek(Node::printChildren)
                .forEach(Node::printNextGeneration);
    }

    public static void main(String[] args) {
        Node root = new Node("1");
        Node firstChild = new Node("1. Kind von 1");
        root.addChild(firstChild);
        root.addChild(new Node("2. Kind von 1"));
        root.addChild(new Node("3. Kind von 1"));
        root.addChild(new Node("4. Kind von 1"));

        Node childOfChild = new Node("Kind von 1.Kind von 1");
        firstChild.addChild(childOfChild);

        Node grandChild = new Node("Enkelkind von 1");
        childOfChild.addChild(grandChild);

        Node greatGrandChild = new Node("Urenkelkind von 1");
        grandChild.addChild(greatGrandChild);

        System.out.println("Methode Kinder");
        root.printChildren();
        System.out.printf("Anzahl Kindern: %d\n", root.getChildCount());

        System.out.println("Methode zeige naechste Generationen");
        root.printNextGeneration();
    }

    private String getData() {
        return this.data;
    }

    private Node[] getChildren() {
        return this.children;
    }

    private int getChildCount() {
        return children.length;
    }

    private void setParent(Node parent) {
        this.parent = parent;
    }

    private Node getParent() {
        return parent;
    }

    private int getAncestorCount() {
        Node parent = getParent();
        int ancestorCount = 0;
        while (parent != null) {
            ancestorCount++;
            parent = parent.getParent();
        }

        return ancestorCount;
    }

    private static Node[] copyArrayWithOneExtra(Node[] children) {
        Node[] newChildren = new Node[children.length + 1];
        System.arraycopy(children, 0, newChildren, 0, children.length);

        return newChildren;
    }
}

Lustig, dass Du Java wählst. SAP kann ja inzwischen auch Java. ABAP ist dann noch ein anderes Thema.

Gruß und viel Spaß

0
Dieter987 
Fragesteller
 24.12.2019, 16:39
@AldoradoXYZ

Vielen Dank für Ihre Bemühungen! Frohes Weihnachtsfest!

0
AldoradoXYZ  24.12.2019, 16:41
@Dieter987

Immer gerne.

Viel Erfolg mit der Aufabe und auch schöne Weihnachten.

Gruß

0

ich vermute, du beziehst dich auf deine zwei Print-Methoden.

Du veränderst die globale Variable des Objekts darin, wodurch du Knoten möglicherweise unwiederruflich löschst.

Zur Lösung des Problems kannst du lokale Variablen nutzen, die du verwendest, um durch die Knoten zu iterieren, statt die globale Variable zu verändern.


Dieter987 
Fragesteller
 24.12.2019, 14:10

Also müsste man in den print Methoden eine neues Objekt erzeugen vom Typ Node und dann zuweisen (nodetwo=node) sowie nodetwo für die Iterierung verwenden?

1
Destranix  24.12.2019, 14:12
@Dieter987

Ja, soinetwa. Nur dass du kein neues Objekt erzeugst, sondern lediglich eine Variable, die auf dein Node-Objekt zeigt. Das kommt aber schlußendlich auf dasselbe raus.

0
Dieter987 
Fragesteller
 24.12.2019, 14:28
@Destranix

Habe nun die Variable erzeugt folgendermaßen:

 public void printchildren(Node node)
	   {
		   Node nodetwo=node;
		   int i=0;
		   while(nodetwo.children!=null) {
			   System.out.println(nodetwo.children.node.data);
		   nodetwo.children=nodetwo.children.next;
		   i++;
		   }
		   System.out.printf("Anzahl Kinder: %d\n",i);
	   }

Was ist mit der Variable in der Mainmethode muss dies auch geändert werden?

0
Destranix  24.12.2019, 14:31
@Dieter987

An sich nicht. Kommt halt darauf an, was du machen willst, das hat jetzt nichts mit den Print_Methoden zu tun.

0