Hallo,
Mir ist heute eine Frage in den Sinn gekommen, die Rekursion und Iteration betrifft. Ich habe 2 Methoden geschrieben, eine rekursiv, die andere iterativ, um Elemente an eine Warteschlange, also eine einfach verkettete FIFO-Liste anzuhaengen. (Wie wird das eigentlich ausgesprochen? F-I-F-O oder fiefoh?) Ausserdem habe ich noch eine dritte Methode geschrieben, die vermutlich besser als beide vorherigen ist, jedoch interessieren mich die beiden vorherigen trotzdem. Hier erstmal der Quellcode:
Scheint soweit alles zu funktionieren. Wenn ich die Landau-Notation richtig verstanden habe (kann durchaus sein, dass das nicht der Fall ist), dann hat die dritte Methode eine Laufzeit von O(1) und ist damit kaum zu toppen.
Da sind jedoch noch die ersten beiden Methoden. Also eine kleine Fallunterscheidung.
Gilt jeweils fuer einen Methodenaufruf bei der rekursiven oder einen Schleifendurchlauf bei der iterativen Methode:
Falls Zeiger.next != null:
rekursiv: 1 Abfrage + 1 Methodenaufruf = 2
iterativ: 1 Abfrage + 1 Zuweisung = 2
Falls Zeiger.next == null:
rekursiv: 1 Abfrage + 1 Zuweisung = 2
iterativ: 1 Abfrage + 1 Zuweisung = 2
Fuer beide Methoden gilt (glaube ich) eine Laufzeit von O(n), n entspricht der Anzahl der Listenelemente. Damit sind sie deutlich langsamer als die 3. Methode, aber welche von den beiden ersten ist schneller? Dauert ein Methodenaufruf laenger als eine Zuweisung oder ist die iterative Methode sowieso aufgrund der geringeren (?) Arbeitsspeicherbelastung vorzuziehen?
Mir kommen rekursive Algorithmen immer ein wenig eleganter vor...
Vielen Dank fuer Antworten!
Jake
Mir ist heute eine Frage in den Sinn gekommen, die Rekursion und Iteration betrifft. Ich habe 2 Methoden geschrieben, eine rekursiv, die andere iterativ, um Elemente an eine Warteschlange, also eine einfach verkettete FIFO-Liste anzuhaengen. (Wie wird das eigentlich ausgesprochen? F-I-F-O oder fiefoh?) Ausserdem habe ich noch eine dritte Methode geschrieben, die vermutlich besser als beide vorherigen ist, jedoch interessieren mich die beiden vorherigen trotzdem. Hier erstmal der Quellcode:
Java:
public class List //Beginn der Liste, zeigt auf ersten Knoten
{
private Node next; //Zeiger auf ersten bzw. auf den naechsten Knoten
private List currentNode; //Zeiger, der immer auf den "aktuellen" Knoten zeigt, wichtig fuer 3. Implementierung
public List()
{
this.currentNode = this;
}
public Node getNext() //Methode fuer die Testklasse
{
return next;
}
public void appendRec(Node n) //Die rekursive Methode
{
if (next != null)
next.appendRec(n);
else
next = n;
}
public void appendIt(Node n) //Die 1. iterative Methode
{
List localCurrent = this;
while (localCurrent.next != null)
{
localCurrent = localCurrent.next;
}
localCurrent.next = n;
}
public void append3(Node n) //Die 3. Methode,
{ //liesse sich mit leichter Modifikation vermutlich
currentNode.next = n; //auch gut fuer LIFO-Stacks verwenden
currentNode = currentNode.next;
}
}
public class Node extends List //Als Subklasse von List implementiert, um die Methoden einfacher implementieren zu koennen
{
private String element;
public Node(String e)
{
this.element = e;
}
public void print() //Methode fuer die Testklasse
{
System.out.println(element);
}
}
public class TestList //Eine kleine Testklasse
{
public static void main(String args[])
{
List list1 = new List();
List list2 = new List();
List list3 = new List();
String i = new String("1");
String ii = new String("2");
String iii = new String("3");
list1.appendRec(new Node(i));
list1.appendRec(new Node(ii));
list1.appendRec(new Node(iii));
list2.appendIt(new Node(i));
list2.appendIt(new Node(ii));
list2.appendIt(new Node(iii));
list3.append3(new Node(i));
list3.append3(new Node(ii));
list3.append3(new Node(iii));
list1.getNext().print();
list1.getNext().getNext().print();
list1.getNext().getNext().getNext().print();
list2.getNext().print();
list2.getNext().getNext().print();
list2.getNext().getNext().getNext().print();
list3.getNext().print();
list3.getNext().getNext().print();
list3.getNext().getNext().getNext().print();
}
}
Scheint soweit alles zu funktionieren. Wenn ich die Landau-Notation richtig verstanden habe (kann durchaus sein, dass das nicht der Fall ist), dann hat die dritte Methode eine Laufzeit von O(1) und ist damit kaum zu toppen.
Da sind jedoch noch die ersten beiden Methoden. Also eine kleine Fallunterscheidung.
Gilt jeweils fuer einen Methodenaufruf bei der rekursiven oder einen Schleifendurchlauf bei der iterativen Methode:
Falls Zeiger.next != null:
rekursiv: 1 Abfrage + 1 Methodenaufruf = 2
iterativ: 1 Abfrage + 1 Zuweisung = 2
Falls Zeiger.next == null:
rekursiv: 1 Abfrage + 1 Zuweisung = 2
iterativ: 1 Abfrage + 1 Zuweisung = 2
Fuer beide Methoden gilt (glaube ich) eine Laufzeit von O(n), n entspricht der Anzahl der Listenelemente. Damit sind sie deutlich langsamer als die 3. Methode, aber welche von den beiden ersten ist schneller? Dauert ein Methodenaufruf laenger als eine Zuweisung oder ist die iterative Methode sowieso aufgrund der geringeren (?) Arbeitsspeicherbelastung vorzuziehen?
Mir kommen rekursive Algorithmen immer ein wenig eleganter vor...
Vielen Dank fuer Antworten!
Jake
Zuletzt bearbeitet: