/media/sda-magnetic/david/Dok-15-2023-11-27/fernuni-hagen/cs-i-ii/old-cs-2-03/java-new/2020-11-23/fernunihagen.txt


Sie finden das auch auf meiner Homepage:

http://www.ituenix.de/phpBB3 - keine Sorge, das ist meine Homepage und nicht abgeschrieben. 


OK, ich habe das mit dem [code]Comparable[/code] verstanden.


Das erste ist, wir machen einen parametrisierten Stack

[code]
class ParamStackProgTest {
    public static void main (String [] args) {
        ParamStack <String> stck = new ParamStack <String> (args[0]);
        int i;
        
        for (i = 1;  i < args.length;  i++)
            stck.put (args[i]);
        
        for (i = 0;  i < args.length + 4;  i++)
            System.out.println (stck.get());
    }
    
    static class ParamStack <P> {
        P v;
        ParamStack <P> n;
        
        ParamStack (P v) {
            this.v = v;
            this.n = null;
        }
        
        void put (P v) {
            ParamStack <P> ptr = new ParamStack (v);
            ptr.n = this.n;
            this.n = ptr;
        }
        
        P get () {
            P v;
            if (this.n == null) 
                v = this.v;
            else {
                v = this.n.v;
                this.n = this.n.n;
            }
            return v;
        }
    
    }

}
[/code]

Den  habe ich an dieser Stelle vom Kopf her etwas komisch implementiert, gebe ich zu. Es hat einen Vorteil, es gibt niemals einen Stack-Overflow - jedes Mal, wenn wir vom Stack abheben und wir haben die untere Grenze erreicht, kommt das letzte Element. Nachteil: Der Stack wird automatisch mit dem Konstruktur realisiert und enthält immer ein Element.



Jetzt, der Witz bei der Geschichte ist, mit dem Baum geht es nicht mehr so einfach, hier eine Version eines Baums ohne Parameter [code]<P>[code]

[code]
class ParamTreeProgTest {
    public static void main (String [] args) {
        int i;
        TreeNode root = new TreeNode (args[0]);
        
        for (i = 1;  i < args.length;  i++)
            root.treenodeInsert (args[i]);
            
        root.treenodePrint();
    }
    public static class TreeNode {
        TreeNode l;
        TreeNode r;
        String v;
        
        TreeNode (String v) {
            this.l = null;
            this.r = null;
            this.v = v;
        }
        
        void treenodeInsert (String v) {
            if (this.v.compareTo (v) < 0) {
                if (this.l == null)
                    this.l = new TreeNode(v);
                else
                    this.l.treenodeInsert (v);
            }
            else {
                if (this.r == null)
                    this.r = new TreeNode (v);
                else
                    this.r.treenodeInsert (v);
            }
        }
        
        void treenodePrint () {
            if (this.l != null)
                this.l.treenodePrint();
            System.out.println (this.v);
            if (this.r != null)
                this.r.treenodePrint();
        }
    }
}

[/code]

Das Problem ist in erster Linie, die Methode [code]compareTo()[/code]. Bei irgendeinem Parameter, wissen wir nicht woher diese stammt. Auch beim Ausdrucken wird es ein Problem. Weil bei irgendeinem Parameter lässt sich [code]System.out.println()[/code] nicht anwenden, weil: Es erwartet [code]String[/code]

Das ist aber das geringere Problem - weil wir den Baum nicht ausgeben müssen, sondern wir müssen vergleichen, damit wir die Knoten richtig einordnen - meine Lösung, ohne das Vergleichen, sieht so aus, dass eine Zufallszahl 1 oder 0 generiert wird und der Knoten irgendwo eingefügt wird. Das ist aber kein Sortierbaum und den wollen wir auch realisieren.



Hier mit zufälliger Ein-Ordnung

[code]

import java.util.Random;

public class BinTreeProg {

    public static void main (String [] argv) {
        
        
    }
        
    static class BinTree <T> {
        T v;
        BinTree <T> l;
        BinTree <T> r;
        
        BinTree (T v) {
            this.v = v;
            this.l = null;
            this.r = null;
        }   
        
        void insertBinTree (T v) {
            Random rnd = new Random();
            int i = rnd.nextInt(2);
            
            if (i == 1) {
                if (this.l == null) 
                    this.l = new BinTree (v);
                else
                    this.l.insertBinTree(v);
            }
            else {
                if (this.r == null)
                    this.r = new BinTree (v);
                else
                    this.r.insertBinTree (v);
            }
        }
        
        BinTree getleftBinTree () {
            return this.l;
        }

        BinTree getrightBinTree () {
            return this.r;
        }

        
        T getvalBinTree () {
            return this.v;
        }
    }
    
}


Jetzt gibt es allerdings eine Lösung und wir werden sehen, diese schlägt zwei Fliegen in einer Klappe. Nicht nur [code]compareTo()[/code], sondern auch [code]toString()[/code] wird realisiert. Was nutzt uns [code]toString()[/code]? Na ganz einfach. Wenn wir [code]System.out.println()[/code] machen, dann können wir auch [code]toString()[/code] von dem Objektaufrufen und das ausgeben


Hier erst Mal die Lösung:

[code]
class ParamTreeProgTest2 {
    public static void main (String [] args) {
        int i;
        TreeNode <Str> root = new TreeNode <Str> (new Str(args[0]));
        
        for (i = 1;  i < args.length;  i++)
            root.treenodeInsert (new Str(args[i]));
            
        root.treenodePrint();
    }
    
    public static class Str implements Comparable {
        private String src;
        
        public Str (String src) {
            this.src = src;
        }
        
        @Override
        public int compareTo (Object o) {
            Str des = (Str) o;
            return this.src.compareTo (des.src);
        }
        @Override
        public String toString () {
            return src;
        }
    }
    
    
    public static class Person implements Comparable {
        private String firstName;
        private String lastName;

        public Person(String firstName, String lastName)    {
            this.firstName = firstName;
            this.lastName = lastName;
        }

        public String getFirstName() {
            return firstName;
        }

        public String getLastName() {
            return lastName;
        }

        @Override
        public String toString() {
            return "Person{firstName='" + firstName + "', lastName='" + lastName + "'}";
        }

        @Override
        public int compareTo(Object o) {
            Person other = (Person) o;
            return this.lastName.compareTo(other.lastName);
        }
    }
    
    public static class TreeNode <P extends Comparable> {
        TreeNode l;
        TreeNode r;
        P v;
        
        TreeNode (P v) {
            this.l = null;
            this.r = null;
            this.v = v;
        }
        
        void treenodeInsert (P v) {
            if (this.v.compareTo (v) < 0) {
                if (this.l == null)
                    this.l = new TreeNode(v);
                else
                    this.l.treenodeInsert (v);
            }
            else {
                if (this.r == null)
                    this.r = new TreeNode (v);
                else
                    this.r.treenodeInsert (v);
            }
        }
        
        void treenodePrint () {
            if (this.l != null)
                this.l.treenodePrint();
            System.out.println (this.v.toString());
            if (this.r != null)
                this.r.treenodePrint();
        }
    }
}
[/code]

wie wir sehen, funktioniert diese sowohl mit Personen als auch Strings.


Die Lösung iiegt daran. Normalerweise schreiben wir für Parametrisierte Klassen 

[code]
class XYZ <P> {

}
[/code]

Wir können allerdings eine beschränkt parametrisierte Klasse zu lassen:

[code]
class XYZ <P extends ABC> {

}
[/code]

Hier ist [code]ABC[/code] die Superklasse.

Es gibt jetzt eine Klasse, die wurde als Interface definiert

[code]
Comparable
[/code]

Und mit [code]Override[/code] definieren wir in dieser überall 

[code]
compareTo()
toString()
[/code]

Aber wir müssen nicht [code]toString()[/code] realisieren, aber wir können es. [code]compareTo()[/code] wäre angebracht. Aber, wenn wir das machen, überschreiben wir jedes Mal die alte abstrakte Klasse, unsere Superklasse. In 

[code]
class XYZ <P extends ABC> {

}
[/code]


Ist [code]ABC[/code] die Superklasse und wir schreiben;

[code]
class XYZ <P extends Comparable> {

}
[/code]

[Comparable] ist dabei eine abstrakte Superklasse, die irgendwo definiert wurde. Und wir können in ihr [code]compareTo()[/code] neu definieren. Da wir bei dem Baum-Knoten allerdings nur eine beschränkt parametrisierte Superklasse zugelassen haben, lässt sich das damit realisieren.