Um den Zeitunterschied zu verstehen, schauen wir uns an, was Sie da eigentlich machen.
In Ihrem ersten Beispiel nehmen Sie eine leere Liste und fügen Sie Elemente an, und sortieren sie am Ende.
Anhängen an Listen ist wirklich billig, es hat eine amortized time complexity von O (1). Es kann keine wirklich konstante Zeit sein, da die zugrunde liegende Datenstruktur, ein einfaches Array, eventuell erweitert werden muss, wenn die Liste wächst. Dies wird gelegentlich durchgeführt, wodurch ein neues Array zugewiesen und die Daten kopiert werden. Das ist ein bisschen teurer. Aber im Allgemeinen we still say this is O(1).
Als nächstes kommt die Sortierung. Python verwendet Timsort, was sehr effizient ist. Dies ist O (n log n) im Durchschnitt und im schlimmsten Fall. Insgesamt erhalten wir konstante Zeit nach O(n log n)
, so dass die Sortierung das einzige ist, was hier zählt. Insgesamt ist das ziemlich einfach und sehr schnell.
Das zweite Beispiel verwendet bisect.insort
. Dies verwendet eine Liste und binäre Suche, um sicherzustellen, dass die Liste immer sortiert ist.
Im Wesentlichen wird bei jeder Einfügung die binäre Suche verwendet, um die korrekte Position zum Einfügen des neuen Werts zu finden, und dann werden alle Elemente korrekt verschoben, um Platz für diesen Index für den neuen Wert zu schaffen. Binäre Suche ist billig, O (log n) im Durchschnitt, das ist also kein Problem. Alleine zu wechseln ist auch nicht so schwierig. Im schlimmsten Fall müssen wir alle Elemente um einen Index nach rechts verschieben, also erhalten wir O (n) (das ist im Grunde die insert operation on lists).
Also würden wir im schlimmsten Fall lineare Zeit bekommen. Wir tun dies jedoch auf jeder einzelnen Iteration. Wenn wir n
Elemente einfügen, haben wir jedesmal O (n). Dies führt zu einer quadratischen Komplexität O (n²). Das ist ein Problem und wird das Ganze letztendlich verlangsamen.
Was sagt uns das? Sorted inserting in eine Liste, um ein sortiertes Ergebnis zu bekommen, ist nicht wirklich performant. Wir können das bisect
-Modul verwenden, um eine bereits sortierte Liste geordnet zu halten, wenn wir nur ein paar Operationen durchführen, aber wenn wir tatsächlich unsortierte Daten haben, ist es einfacher, die Daten als Ganzes zu sortieren.
Weil timsort ein effizienter Sortieralgorithmus ist und Listeneinfügungen langsam sind? – jonrsharpe
Das ist wahrscheinlich der Grund, aber was ist dann der Vorteil von bisect? –
Was meinst du? Wenn Sie bereits eine sortierte Liste haben und diese sortiert halten möchten, ist das der beste Weg. Und viele andere Operationen sind in einer sortierten Liste effizienter. – jonrsharpe