Wenn wir einen Schritt zurücktreten, könnte es scheinen, dass die einfache Entfernung von Duplikaten der einzige Vorteil der Verwendung von Units ist. Wir haben zuvor besprochen, dass Mengen keine Ordnung haben; Arrays verfügen über ein indiziertes Factor, das einfach ignoriert und wie eine Menge behandelt werden kann. Es scheint, dass Arrays die gleiche Aufgabe erfüllen können wie eine Menge, wenn nicht sogar mehr.
Diese durch Mengen erzwungene Vereinfachung eröffnet jedoch den Weg dazu verschiedene zugrunde liegende Implementierungen. In Hear werden Elementen Indizes zugewiesen, um jedem Factor einen Platz in der Reihenfolge zu geben. Units müssen keine Indizes zuweisen, daher implementieren sie stattdessen einen anderen Referenzierungsansatz: Hash-Mapping. Diese funktionieren, indem sie Elementen (pseudo)zufällig Adressen zuweisen, anstatt sie in einer Reihe zu speichern. Die Zuordnung wird durch Hashing-Funktionen gesteuert, die das Factor als Eingabe für die Ausgabe einer Adresse verwenden.
H(x) ist deterministisch, daher liefert die gleiche Eingabe immer die gleiche Ausgabe, d. h. Es gibt kein RNG innerhalb der Funktion H, daher ist in diesem Fall immer H(4) = 6.
Das Ausführen dieser Funktion dauert unabhängig von der Größe des Satzes gleich lange, d. h. Hashing hat eine Zeitkomplexität von O(1). Dies bedeutet, dass die zum Hashing benötigte Zeit unabhängig von der Größe der Liste ist und eine konstante, schnelle Geschwindigkeit aufweist.
Da Hashing im Allgemeinen schnell ist, können eine ganze Reihe von Vorgängen, die bei großen Arrays normalerweise langsam sind, sehr effizient auf einem Satz ausgeführt werden.
Suche oder Mitgliedschaftstest
Die Suche nach Elementen in einem Array verwendet einen Algorithmus namens Lineare Suchevon Überprüfen Sie jedes Factor in der Liste einzeln. Im schlimmsten Fall, wenn das gesuchte Factor nicht in der Liste vorhanden ist, durchläuft der Algorithmus jedes Factor der Liste (An)). Bei einer sehr großen Liste dauert dieser Vorgang sehr lange.
Da das Hashing jedoch O(1) ist, hasht Python das zu findende Factor und gibt entweder dorthin zurück, wo es sich im Speicher befindet, oder dass es nicht existiert – und das in sehr kurzer Zeit.
number_list = vary(random.randint(1,000,000))
number_set = set(number_list)#Line 1
#BEGIN TIMER
print(-1 in number_list)
#END TIMER
#Line 2
#BEGIN TIMER
print(-1 in number_set)
#END TIMER
Hinweis: Die Suche mithilfe einer Hashmap hat einen amortisiert Zeitkomplexität von O(1). Das bedeutet, dass es im Durchschnitt mit einer konstanten Zeit läuft, aber technisch gesehen ist die Suche im schlimmsten Fall O(n). Dies ist jedoch äußerst unwahrscheinlich und liegt daran, dass bei der Hashing-Implementierung die Gefahr von Kollisionen besteht, wenn mehrere Elemente in einer Hashmap/einem Hashsatz an dieselbe Adresse gehasht werden.
Streichung
Das Löschen eines Parts aus einer Liste erfordert zunächst eine Suche nach dem Factor und anschließend das Entfernen des Verweises auf das Factor durch Löschen der Adresse. In einem Array muss nach der O(n)-Zeitsuche der Index jedes Parts, das auf das gelöschte Factor folgt, um eins nach unten verschoben werden. Dies selbst ist ein weiterer O(n)-Prozess.
Das Löschen eines Parts aus einer Menge erfordert die O(1)-Suche und das anschließende Löschen der Speicheradresse, was ein O(1)-Prozess ist, sodass das Löschen ebenfalls in konstanter Zeit erfolgt. Units verfügen außerdem über mehr Möglichkeiten zum Löschen von Elementen, sodass keine Fehler auftreten oder mehrere Elemente präzise entfernt werden können.
#LIST
numbers = (1, 3, 4, 7, 8, 11)numbers.take away(4)
numbers.take away(5) #Raises ERROR as 5 is just not in checklist
numbers.pop(0) #Deletes quantity at index 0, ie. 1
#SET
numbers = {1, 3, 4, 7, 8, 11}
numbers.take away(4)
numbers.take away(5) #Raises ERROR as 5 is just not in set
numbers.discard(5) #Doesn't increase error if 5 is just not within the set
numbers -= {1,2,3} #Performs set distinction, ie. 1, 3 are discarded
Einfügen
Sowohl das Anhängen an eine Liste als auch das Hinzufügen von Elementen zu einer Menge sind konstante Vorgänge; Das Hinzufügen zu einem angegebenen Index in einer Liste (.insert) bringt jedoch die zusätzliche Zeit mit sich, Elemente zu verschieben.
num_list = (1,2,3)
num_set = {1,2,3}num_list.append(4)
num_set.add(4)
num_list += (5,6,7)
num_set += {5,6,7}
Erweiterte Set-Operationen
Darüber hinaus sind alle mathematischen Operationen, die auf Mengen ausgeführt werden können, auch in Python implementiert. Die manuelle Ausführung dieser Vorgänge an einer Liste ist erneut zeitaufwändig und wird erneut mithilfe von Hashing optimiert.
A = {1, 2, 3, 5, 8, 13}
B = {2, 3, 5, 7, 13, 17}# A n B
AintersectB = A & B
# A U B
AunionB = A | B
# A B
AminusB = A - B
# A U B - A n B or A Delta B
AsymmetricdiffB = A ^ B
Dazu gehören auch Vergleichsoperatoren, nämlich echte und entspannte Teilmengen und Obermengen. Diese Operationen laufen wiederum viel schneller als ihre Hear-Gegenstücke und arbeiten in O(n)-Zeit, wobei n die größere der beiden Mengen ist.
A <= B #A is a correct subset of B
A > B #A is a superset of B
Gefrorene Units
Eine letzte kleine, aber unterschätzte Funktion in Python ist die gefrorenes Setwas im Wesentlichen ein schreibgeschütztes oder ist unveränderlich Satz. Diese bieten eine höhere Speichereffizienz und können in Fällen nützlich sein, in denen Sie die Mitgliedschaft in einem Tupel häufig testen.
CEinschluss
Die Essenz der Verwendung von Units zur Leistungssteigerung wird durch das Prinzip zusammengefasst Optimierung durch Reduktion.
Datenstrukturen wie Hear verfügen über die größte Funktionalität – sie sind indiziert und dynamisch –, gehen jedoch mit einer vergleichsweise geringeren Effizienz einher: Geschwindigkeit und Speicher. Wenn Sie ermitteln, welche Funktionen wesentlich bzw. ungenutzt sind, um zu ermitteln, welcher Datentyp verwendet werden soll, erhalten Sie Code, der schneller ausgeführt und besser gelesen werden kann.
Alle technischen Diagramme nach Autor.