2016-04-14 8 views
7

Ich las eine previous question über die Zeit Komplexität für TreeSet und die Antwort war, dass es O (n) Zeit dauert. Ich verstehe jedoch nicht, warum O (n) anstelle von O (n * nlogn) iteriert wird.Warum ist TreeSet Iteration O (n) anstelle von O (n * logn)?

Jeder nächsten Anruf nimmt O(logn) time

Also, wenn ich durch eine TreeSet wie folgt durchlaufen:

while (iterator.hasNext()){ //Runs N times 
    System.out.println(iterator.next() + " "); //each next is O(logn) 
} 

Ich würde erwarten, denn es O (n * log n) und nicht O (n) sein, weil Die while-Schleife hat N Iterationen und jeder iterator.next() -Aufruf benötigt O (logn) -Zeit.

+0

Warum 'iterator.next()' ist O (log n). Es muss nur zum nächsten Knoten gehen, das ist O (1), oder? –

+2

@JoseLuis ist nicht genau, basierend auf dem Quellcode. –

+0

@ louis-wasserman Du hast Recht, es tut mir sehr leid. Ich dachte, dass iterator() eine Liste mit den sortierten Knoten zurückgeben könnte, und dann zum nächsten Knoten zu gehen ist einfach. –

Antwort

12

Die Worst-Case-Zeit für eine next Operation ist O(log n), denn das ist die Höhe des Baumes. Im Durchschnitt kann jedoch das nächste Element in der Zeit O(1) gefunden werden. Dies liegt daran, dass die gesamte Traversierung im Wesentlichen jede der Baumränder n-1 zweimal verwendet.

+1

Der Code für Iterator.next erscheint anscheinend in 'TreeMap.Entry.successor()', hier: http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6- b14/java/util/TreeMap.java # TreeMap.successor% 28java.util.TreeMap.Entry% 29 Ja, es scheint, dass der nächste Eintrag meistens "p.left! = null" ist. Aber sollte Big-O nicht der schlechteste sein, nicht der Durchschnitt? – markspace

+1

@markspace Big-O beschreibt, was auch immer Sie wollen, da es nicht um Komplexität per se geht, sondern um das Wachstum von Funktionen. Sie können durchschnittliche, ungünstigste, amortisierte, erwartete Kosten mit hoher Wahrscheinlichkeit beschreiben ... In diesem Fall ist es sogar Theta (n) (schlimmster und bester Fall) für alle Operationen zusammen. Das Finden eines einzelnen Nachfolgers könnte log n Zeit kosten, aber das Iterieren aller n Elemente kostet höchstens 2 n. –

+1

@markspace Eine große O-Grenze ohne Ausarbeitung bezieht sich auf die Worst-Case-Laufzeit, aber die Groß-O-Notation ist nur eine mathematische Aussage über eine Funktion. –

0

Sie können die Iteration für einen Baum wie folgt implementieren:

void print(Node n) { 
    if (n.left != null) print(n.left); 
    System.out.println(n.value); 
    if (n.right != null) print(n.right); 
} 

Die Funktion Druck für jeden Knoten genau einmal werden wird aufgerufen, so dass die Gesamt Iterationszeit O (N) ist. Sie können den gleichen Algorithmus iterativ (ohne Rekursion) implementieren. Und wenn Sie vorsichtig genug sind, können Sie eine Klasse haben, um den Iterationsstatus beizubehalten und fortzufahren, wenn .next() aufgerufen wird. Es ist wahr, dass die Anzahl der Funktionsaufrufe zwischen println s ungleich ist, aber wenn Sie es insgesamt betrachten, werden Sie feststellen, dass es genau N von ihnen gibt.