Ich verwende viele Listen und Arrays, aber ich muss noch auf ein Szenario stoßen, in dem die Array-Liste nicht genauso einfach verwendet werden kann wie die verknüpfte Liste, wenn nicht sogar einfacher als diese. Ich hatte gehofft, jemand könnte mir einige Beispiele geben, wann die verknüpfte Liste deutlich besser ist.
arrays
list
arraylist
linked-list
gesichtslos1_14
quelle
quelle
Antworten:
Verknüpfte Listen sind Arrays vorzuziehen, wenn:
Sie benötigen Einfügungen / Löschungen mit konstanter Zeit aus der Liste (z. B. beim Echtzeit-Computing, bei dem die Vorhersagbarkeit der Zeit absolut kritisch ist).
Sie wissen nicht, wie viele Elemente in der Liste enthalten sein werden. Bei Arrays müssen Sie möglicherweise den Speicher neu deklarieren und kopieren, wenn das Array zu groß wird
Sie benötigen keinen zufälligen Zugriff auf Elemente
Sie möchten in der Lage sein, Elemente in die Mitte der Liste einzufügen (z. B. eine Prioritätswarteschlange).
Arrays sind vorzuziehen, wenn:
Sie benötigen einen indizierten / zufälligen Zugriff auf Elemente
Sie kennen die Anzahl der Elemente im Array im Voraus, damit Sie die richtige Speichermenge für das Array zuweisen können
Sie benötigen Geschwindigkeit, wenn Sie alle Elemente nacheinander durchlaufen. Sie können Zeigermathematik für das Array verwenden, um auf jedes Element zuzugreifen, während Sie den Knoten basierend auf dem Zeiger für jedes Element in der verknüpften Liste suchen müssen, was zu Seitenfehlern führen kann, die zu Leistungseinbußen führen können.
Erinnerung ist ein Anliegen. Gefüllte Arrays beanspruchen weniger Speicher als verknüpfte Listen. Jedes Element im Array sind nur die Daten. Jeder verknüpfte Listenknoten benötigt die Daten sowie einen (oder mehrere) Zeiger auf die anderen Elemente in der verknüpften Liste.
Array-Listen (wie die in .Net) bieten Ihnen die Vorteile von Arrays, weisen Ihnen jedoch dynamisch Ressourcen zu, sodass Sie sich nicht zu viele Gedanken über die Listengröße machen müssen und Elemente an jedem Index ohne Aufwand oder erneutes Löschen löschen können Elemente mischen. In Bezug auf die Leistung sind Arraylisten langsamer als Raw-Arrays.
quelle
Arrays haben einen O (1) -Wahlzugriff, aber das Hinzufügen oder Entfernen von Inhalten ist sehr teuer.
Verknüpfte Listen sind wirklich billig, um Elemente überall hinzuzufügen oder zu entfernen und zu iterieren, aber der Direktzugriff ist O (n).
quelle
ArrayLists eignen sich gut zum Schreiben, einmal Lesen, Lesen oder Anhängen, aber schlecht zum Hinzufügen / Entfernen von vorne oder in der Mitte.
quelle
Um die anderen Antworten zu ergänzen, reservieren die meisten Implementierungen von Array-Listen zusätzliche Kapazität am Ende der Liste, sodass neue Elemente in O (1) -Zeit am Ende der Liste hinzugefügt werden können. Wenn die Kapazität einer Array-Liste überschritten wird, wird intern ein neues, größeres Array zugewiesen und alle alten Elemente werden kopiert. Normalerweise ist das neue Array doppelt so groß wie das alte. Dies bedeutet, dass das Hinzufügen neuer Elemente am Ende einer Array-Liste in diesen Implementierungen im Durchschnitt eine O (1) -Operation ist. Selbst wenn Sie die Anzahl der Elemente nicht im Voraus kennen, ist eine Array-Liste möglicherweise immer noch schneller als eine verknüpfte Liste zum Hinzufügen von Elementen, solange Sie sie am Ende hinzufügen. Offensichtlich ist das Einfügen neuer Elemente an beliebigen Stellen in eine Array-Liste immer noch eine O (n) -Operation.
Der Zugriff auf Elemente in einer Array-Liste ist auch schneller als bei einer verknüpften Liste, selbst wenn die Zugriffe sequentiell sind. Dies liegt daran, dass Array-Elemente im zusammenhängenden Speicher gespeichert werden und einfach zwischengespeichert werden können. Verknüpfte Listenknoten können möglicherweise auf viele verschiedene Seiten verteilt sein.
Ich würde empfehlen, nur eine verknüpfte Liste zu verwenden, wenn Sie wissen, dass Sie Elemente an beliebigen Stellen einfügen oder löschen werden. Array-Listen sind für so ziemlich alles andere schneller.
quelle
Der Vorteil von Listen wird angezeigt, wenn Sie Elemente in der Mitte einfügen müssen und nicht mit der Größenänderung des Arrays und dem Verschieben von Elementen beginnen möchten.
Sie haben Recht, dass dies normalerweise nicht der Fall ist. Ich hatte einige sehr spezifische Fälle wie diesen, aber nicht zu viele.
quelle
Es hängt alles davon ab, welche Art von Operation Sie während der Iteration ausführen. Alle Datenstrukturen haben einen Kompromiss zwischen Zeit und Speicher. Abhängig von unseren Anforderungen sollten wir den richtigen DS auswählen. Es gibt also Fälle, in denen LinkedList schneller als Array ist und umgekehrt. Betrachten Sie die drei grundlegenden Operationen für Datenstrukturen.
Da das Array eine indexbasierte Datenstruktur ist, dauert die Suche nach array.get (index) O (1), während die verknüpfte Liste nicht der Index DS ist. Sie müssen also zum Index wechseln, wobei der Index <= n, n die Größe der verknüpften Liste ist. Das Array ist also schneller als die verknüpfte Liste, wenn Sie zufälligen Zugriff auf Elemente haben.
Frage: Was ist die Schönheit dahinter?
Da Arrays zusammenhängende Speicherblöcke sind, werden beim ersten Zugriff große Teile davon in den Cache geladen. Dies macht den Vergleich auf verbleibende Elemente des Arrays vergleichsweise schnell, da der Zugriff auf die Elemente in der Array-Referenzlokalität ebenfalls zunimmt und somit weniger Fang erfolgt Fehlt, bezieht sich die Cache-Lokalität auf die Operationen, die sich im Cache befinden und daher im Vergleich zum Speicher viel schneller ausgeführt werden. Im Array maximieren wir im Grunde genommen die Wahrscheinlichkeit, dass sich sequentielle Elemente im Cache befinden. Während verknüpfte Listen nicht unbedingt in zusammenhängenden Speicherblöcken enthalten sind, gibt es keine Garantie dafür, dass Elemente, die nacheinander in der Liste erscheinen, tatsächlich nahe beieinander im Speicher angeordnet sind. Dies bedeutet weniger Cache-Treffer, z
Dies ist in LinkedList einfach und schnell, da das Einfügen eine O (1) -Operation in LinkedList (in Java) im Vergleich zum Array ist. Wenn das Array voll ist, müssen wir den Inhalt in ein neues Array kopieren, wenn das Array voll wird, wodurch das Einfügen eines Element in ArrayList von O (n) im schlimmsten Fall, während ArrayList auch seinen Index aktualisieren muss, wenn Sie irgendwo etwas einfügen, außer am Ende des Arrays. Im Fall einer verknüpften Liste müssen wir die Größe nicht ändern, sondern nur Zeiger aktualisieren.
Es funktioniert wie Einfügungen und ist in LinkedList besser als in Arrays.
quelle
Dies sind die am häufigsten verwendeten Implementierungen von Collection.
Anordnungsliste:
Einfügen / Löschen am Ende allgemein O (1) Worst Case O (n)
Einfügen / Löschen in der Mitte O (n)
eine beliebige Position O (1) abrufen
LinkedList:
Einfügen / Löschen an einer beliebigen Position O (1) (Hinweis, wenn Sie einen Verweis auf das Element haben)
in der Mitte abrufen O (n)
erstes oder letztes Element O abrufen (1)
Vektor: benutze es nicht. Es ist eine alte Implementierung, die ArrayList ähnelt, jedoch alle Methoden synchronisiert hat. Dies ist nicht der richtige Ansatz für eine gemeinsam genutzte Liste in einer Multithreading-Umgebung.
HashMap
Einfügen / Löschen / Abrufen durch Eingabe von O (1)
TreeSet einfügen / löschen / enthält in O (log N)
HashSet einfügen / entfernen / enthält / Größe in O (1)
quelle
In der Realität hat die Speicherlokalität einen großen Einfluss auf die Leistung bei der realen Verarbeitung.
Die zunehmende Verwendung von Festplatten-Streaming bei der "Big Data" -Verarbeitung im Vergleich zum Direktzugriff zeigt, wie die Strukturierung Ihrer Anwendung darauf die Leistung in größerem Maßstab erheblich verbessern kann.
Wenn es eine Möglichkeit gibt, nacheinander auf ein Array zuzugreifen, ist dies bei weitem die beste Leistung. Das Entwerfen mit diesem Ziel sollte zumindest in Betracht gezogen werden, wenn Leistung wichtig ist.
quelle
Hmm, Arraylist kann in folgenden Fällen verwendet werden:
Zum Beispiel müssen Sie alle Elemente in einer Kontaktliste importieren und darauf zugreifen (deren Größe Ihnen unbekannt ist).
quelle
Verwenden Sie die verknüpfte Liste für die Radix-Sortierung über Arrays und für Polynomoperationen.
quelle
1) Wie oben erläutert, ergeben die Einfüge- und Entfernungsoperationen in LinkedList im Vergleich zu ArrayList (O (n)) eine gute Leistung (O (1)). Wenn in der Anwendung häufig hinzugefügt und gelöscht werden muss, ist LinkedList die beste Wahl.
2) Suchoperationen (Methode abrufen) sind in Arraylist (O (1)) schnell, jedoch nicht in LinkedList (O (n)). Wenn weniger Operationen zum Hinzufügen und Entfernen und mehr Suchoperationen erforderlich sind, ist ArrayList die beste Wahl.
quelle
Ich denke, der Hauptunterschied besteht darin, ob Sie häufig Dinge am Anfang der Liste einfügen oder entfernen müssen.
Wenn Sie bei einem Array etwas vom Anfang der Liste entfernen, ist die Komplexität o (n), da sich alle Indizes der Array-Elemente verschieben müssen.
Bei einer verknüpften Liste ist dies o (1), da Sie nur den Knoten erstellen, den Kopf neu zuweisen und die Referenz dem nächsten als vorherigen Kopf zuweisen müssen.
Wenn Sie häufig am Ende der Liste einfügen oder entfernen, sind Arrays vorzuziehen, da die Komplexität o (1) beträgt und keine Neuindizierung erforderlich ist. Bei einer verknüpften Liste ist sie jedoch o (n), da Sie vom Kopf abweichen müssen bis zum letzten Knoten.
Ich denke, dass die Suche sowohl in verknüpften Listen als auch in Arrays o (log n) sein wird, da Sie wahrscheinlich eine binäre Suche verwenden werden.
quelle
Ich habe ein Benchmarking durchgeführt und festgestellt, dass die Listenklasse beim zufälligen Einfügen tatsächlich schneller als LinkedList ist:
Es dauert 900 ms für die verknüpfte Liste und 100 ms für die Listenklasse.
Es werden Listen nachfolgender Ganzzahlen erstellt. Jede neue Ganzzahl wird nach einer Zufallszahl eingefügt, die bereits in der Liste enthalten ist. Vielleicht verwendet die List-Klasse etwas Besseres als nur ein Array.
quelle
Arrays sind bei weitem die am häufigsten verwendeten Datenstrukturen. Verknüpfte Listen erweisen sich jedoch auf ihre einzigartige Weise als nützlich, wenn Arrays ungeschickt oder teuer sind, um es gelinde auszudrücken.
Verknüpfte Listen sind nützlich, um Stapel und Warteschlangen in Situationen zu implementieren, in denen ihre Größe variieren kann. Jeder Knoten in der verknüpften Liste kann verschoben oder verschoben werden, ohne die Mehrheit der Knoten zu stören. Gleiches gilt für das Einfügen / Löschen von Knoten irgendwo in der Mitte. In Arrays müssen jedoch alle Elemente verschoben werden, was in Bezug auf die Ausführungszeit eine teure Aufgabe ist.
Binäre Bäume und binäre Suchbäume, Hash-Tabellen und Versuche sind einige der Datenstrukturen, bei denen Sie - zumindest in C - verknüpfte Listen als Grundbestandteil für deren Aufbau benötigen.
Verknüpfte Listen sollten jedoch in Situationen vermieden werden, in denen erwartet wird, dass sie ein beliebiges Element anhand ihres Index aufrufen können.
quelle