Warum sollte jemand eine verknüpfte Liste über ein Array verwenden wollen?
Das Codieren einer verknüpften Liste ist zweifellos etwas mehr Arbeit als das Verwenden eines Arrays, und man kann sich fragen, was den zusätzlichen Aufwand rechtfertigen würde.
Ich denke, das Einfügen neuer Elemente in eine verknüpfte Liste ist trivial, aber es ist eine große Aufgabe in einem Array. Gibt es andere Vorteile bei der Verwendung einer verknüpften Liste zum Speichern eines Datensatzes gegenüber dem Speichern in einem Array?
Diese Frage ist kein Duplikat dieser Frage, da sich die andere Frage speziell auf eine bestimmte Java-Klasse bezieht, während sich diese Frage mit den allgemeinen Datenstrukturen befasst.
arrays
data-structures
linked-list
language-agnostic
Onorio Catenacci
quelle
quelle
Antworten:
quelle
Ein weiterer guter Grund ist, dass sich verknüpfte Listen gut für effiziente Multithread-Implementierungen eignen. Der Grund dafür ist, dass Änderungen in der Regel lokal sind und nur einen oder zwei Zeiger zum Einfügen und Entfernen in einem lokalisierten Teil der Datenstruktur betreffen. Sie können also viele Threads haben, die an derselben verknüpften Liste arbeiten. Darüber hinaus ist es möglich, sperrfreie Versionen mit CAS-Operationen zu erstellen und schwere Sperren insgesamt zu vermeiden.
Mit einer verknüpften Liste können Iteratoren die Liste auch durchlaufen, während Änderungen vorgenommen werden. In dem optimistischen Fall, in dem Änderungen nicht kollidieren, können Iteratoren ohne Konkurrenz fortgesetzt werden.
Bei einem Array erfordert jede Änderung, die die Größe des Arrays ändert, wahrscheinlich das Sperren eines großen Teils des Arrays. Tatsächlich wird dies selten ohne eine globale Sperre für das gesamte Array durchgeführt, sodass Änderungen die Weltgeschehen stoppen.
quelle
ConcurrentSkipListMap
oderConcurrentSkipListMap
sind keine Listen, auch wenn „Liste“ irgendwo in ihrem Namen vorkommt. Beide erfordern Schlüssel, die sortiert und eindeutig sind. Wenn Sie eineList
Datenstruktur benötigen , die doppelte Elemente in einer beliebigen Reihenfolge zulässt, ist dies nicht geeignet, und Sie müssten große Anstrengungen unternehmen, um eine Datenstruktur wieLinkedList
eine gleichzeitig aktualisierbare Sache zu erstellen . Wenn Sie nur eine gleichzeitige Warteschlange oder Deque benötigen, gibt es sogar Beispiele, aber eine gleichzeitigeList
… Ich bin nicht davon überzeugt, dass dies überhaupt möglich ist.Wikipedia hat einen sehr guten Abschnitt über die Unterschiede.
http://en.wikipedia.org/wiki/Linked_list
quelle
Ich werde noch eine hinzufügen - Listen können als rein funktionale Datenstrukturen fungieren .
Beispielsweise können Sie völlig unterschiedliche Listen haben, die denselben Endabschnitt verwenden
dh:
ohne die Daten, auf die von verwiesen wird,
a
inb
und kopieren zu müssenc
.Aus diesem Grunde sind sie so beliebt in funktionalen Sprachen sind, die unveränderlichen Variablen -
prepend
undtail
Operationen auftreten können frei ohne die Originaldaten kopieren zu müssen - sehr wichtige Eigenschaften , wenn Sie Daten als unveränderlich sind zu behandeln.quelle
Das Einfügen in die Mitte der Liste ist nicht nur einfacher, sondern auch viel einfacher aus der Mitte einer verknüpften Liste zu löschen als ein Array.
Aber ehrlich gesagt habe ich noch nie eine verknüpfte Liste verwendet. Wann immer ich schnelles Einfügen und Löschen benötigte, musste ich auch schnell nachschlagen, also ging ich zu einem HashSet oder einem Wörterbuch.
quelle
Das Zusammenführen von zwei verknüpften Listen (insbesondere von zwei doppelt verknüpften Listen) ist viel schneller als das Zusammenführen von zwei Arrays (vorausgesetzt, die Zusammenführung ist destruktiv). Ersteres nimmt O (1), letzteres nimmt O (n).
EDIT: Zur Verdeutlichung meinte ich hier "Zusammenführen" im ungeordneten Sinne, nicht wie beim Zusammenführen. Vielleicht wäre "Verketten" ein besseres Wort gewesen.
quelle
Ein weithin nicht anerkanntes Argument für ArrayList und gegen LinkedList ist, dass LinkedLists beim Debuggen unangenehm sind . Die Zeit, die Wartungsentwickler benötigen, um das Programm zu verstehen, z. B. um Fehler zu finden, nimmt zu, und IMHO rechtfertigt manchmal nicht die Nanosekunden für Leistungsverbesserungen oder Bytes für den Speicherverbrauch in Unternehmensanwendungen. Manchmal (natürlich hängt es von der Art der Anwendungen ab) ist es besser, ein paar Bytes zu verschwenden, aber eine Anwendung zu haben, die wartbarer oder leichter zu verstehen ist.
In einer Java-Umgebung und unter Verwendung des Eclipse-Debuggers zeigt das Debuggen einer ArrayList beispielsweise eine sehr leicht verständliche Struktur:
Auf der anderen Seite wird das Beobachten des Inhalts einer LinkedList und das Finden bestimmter Objekte zu einem Alptraum beim Klicken auf Expand-The-Tree, ganz zu schweigen vom kognitiven Aufwand, der zum Herausfiltern der LinkedList-Interna erforderlich ist:
quelle
Zunächst sollte es in C ++ nicht viel schwieriger sein, mit verknüpften Listen zu arbeiten als mit einem Array. Sie können die std :: list oder die Boost-Zeigerliste für verknüpfte Listen verwenden. Die Hauptprobleme bei verknüpften Listen und Arrays sind zusätzlicher Speicherplatz für Zeiger und ein schrecklicher Direktzugriff. Sie sollten eine verknüpfte Liste verwenden, wenn Sie
quelle
Für mich ist es so,
Zugriff
Lager
Größe
Einfügen / Löschen
quelle
Zwei Dinge:
Codieren Sie niemals eine verknüpfte Liste, wenn Sie C ++ verwenden. Verwenden Sie einfach die STL. Wie schwierig die Implementierung ist, sollte niemals ein Grund sein, eine Datenstruktur einer anderen vorzuziehen, da die meisten bereits implementiert sind.
Was die tatsächlichen Unterschiede zwischen einem Array und einer verknüpften Liste betrifft, ist für mich das Wichtigste, wie Sie die Struktur verwenden möchten. Ich werde den Begriff Vektor verwenden, da dies der Begriff für ein anpassbares Array in C ++ ist.
Die Indizierung in eine verknüpfte Liste ist langsam, da Sie die Liste durchlaufen müssen, um zum angegebenen Index zu gelangen, während ein Vektor im Speicher zusammenhängend ist und Sie mithilfe der Zeigermathematik dorthin gelangen können.
Das Anhängen an das Ende oder den Anfang einer verknüpften Liste ist einfach, da Sie nur einen Link aktualisieren müssen, wobei Sie in einem Vektor möglicherweise die Größe ändern und den Inhalt kopieren müssen.
Das Entfernen eines Elements aus einer Liste ist einfach, da Sie nur ein paar Links trennen und sie dann wieder zusammenfügen müssen. Das Entfernen eines Elements aus einem Vektor kann entweder schneller oder langsamer sein, je nachdem, ob Sie sich für eine Bestellung interessieren. Das Vertauschen des letzten Elements über das Element, das Sie entfernen möchten, ist schneller, während das Verschieben nach dem Herunterfahren langsamer ist, aber die Reihenfolge beibehält.
quelle
Eric Lippert hatte kürzlich einen Beitrag über einen der Gründe, warum Arrays konservativ verwendet werden sollten.
quelle
Schnelles Einfügen und Entfernen sind in der Tat die besten Argumente für verknüpfte Listen. Wenn Ihre Struktur dynamisch wächst und kein zeitlich konstanter Zugriff auf ein Element erforderlich ist (z. B. dynamische Stapel und Warteschlangen), sind verknüpfte Listen eine gute Wahl.
quelle
Hier ist eine kurze Beschreibung: Das Entfernen von Elementen ist schneller.
quelle
Verknüpfte Listen sind besonders nützlich, wenn die Sammlung ständig wächst und schrumpft. Zum Beispiel ist es schwer vorstellbar, eine Warteschlange (am Ende hinzufügen, von vorne entfernen) mithilfe eines Arrays zu implementieren - Sie würden Ihre ganze Zeit damit verbringen, Dinge nach unten zu verschieben. Auf der anderen Seite ist es mit einer verknüpften Liste trivial.
quelle
Abgesehen vom Hinzufügen und Entfernen aus der Mitte der Liste mag ich verknüpfte Listen mehr, weil sie dynamisch wachsen und schrumpfen können.
quelle
Niemand codiert mehr seine eigene verknüpfte Liste. Das wäre dumm. Die Annahme, dass die Verwendung einer verknüpften Liste mehr Code erfordert, ist einfach falsch.
Heutzutage ist das Erstellen einer verknüpften Liste nur eine Übung für die Schüler, damit sie das Konzept verstehen können. Stattdessen verwendet jeder eine vorgefertigte Liste. In C ++ würde das, basierend auf der Beschreibung in unserer Frage, wahrscheinlich einen stl-Vektor (
#include <vector>
) bedeuten .Daher geht es bei der Auswahl einer verknüpften Liste im Vergleich zu einem Array ausschließlich darum, die verschiedenen Merkmale jeder Struktur im Verhältnis zu den Anforderungen Ihrer App abzuwägen. Die Überwindung des zusätzlichen Programmieraufwands sollte keinen Einfluss auf die Entscheidung haben.
quelle
Es ist wirklich eine Frage der Effizienz, der Aufwand für das Einfügen, Entfernen oder Verschieben von Elementen (wo Sie nicht einfach tauschen) innerhalb einer verknüpften Liste ist minimal, dh die Operation selbst ist O (1), Verse O (n) für ein Array. Dies kann einen erheblichen Unterschied machen, wenn Sie stark mit einer Datenliste arbeiten. Sie haben Ihre Datentypen basierend auf der Art und Weise ausgewählt, wie Sie sie bearbeiten, und den effizientesten für den von Ihnen verwendeten Algorithmus ausgewählt.
quelle
Arrays sind sinnvoll, wenn die genaue Anzahl der Elemente bekannt ist und wenn die Suche nach Index sinnvoll ist. Wenn ich beispielsweise den genauen Status meiner Videoausgabe zu einem bestimmten Zeitpunkt ohne Komprimierung speichern möchte, würde ich wahrscheinlich ein Array der Größe [1024] [768] verwenden. Dies liefert mir genau das, was ich brauche, und eine Liste wäre viel, viel langsamer, um den Wert eines bestimmten Pixels zu erhalten. An Orten, an denen ein Array keinen Sinn ergibt, gibt es im Allgemeinen bessere Datentypen als eine Liste, um effektiv mit Daten umzugehen.
quelle
Arrays Vs Linked List:
quelle
Da Arrays statischer Natur sind, werden alle Operationen wie die Speicherzuweisung nur zum Zeitpunkt der Kompilierung ausgeführt. Der Prozessor muss sich also weniger um seine Laufzeit bemühen.
quelle
Angenommen, Sie haben einen geordneten Satz, den Sie auch durch Hinzufügen und Entfernen von Elementen ändern möchten. Außerdem müssen Sie in der Lage sein, einen Verweis auf ein Element so beizubehalten, dass Sie später ein vorheriges oder nächstes Element erhalten können. Zum Beispiel eine Aufgabenliste oder eine Reihe von Absätzen in einem Buch.
Zunächst sollten wir beachten, dass Sie, wenn Sie Verweise auf Objekte außerhalb des Sets selbst beibehalten möchten, wahrscheinlich Zeiger im Array speichern, anstatt Objekte selbst zu speichern. Andernfalls können Sie keine Elemente in das Array einfügen. Wenn Objekte in das Array eingebettet sind, werden sie beim Einfügen verschoben und Zeiger auf sie werden ungültig. Gleiches gilt für Array-Indizes.
Ihr erstes Problem ist, wie Sie selbst bemerkt haben, das Einfügen - eine verknüpfte Liste ermöglicht das Einfügen in O (1), aber ein Array würde im Allgemeinen O (n) erfordern. Dieses Problem kann teilweise überwunden werden - es ist möglich, eine Datenstruktur zu erstellen, die eine Array-ähnliche, ordinale Zugriffsschnittstelle bietet, bei der sowohl Lesen als auch Schreiben im schlimmsten Fall logarithmisch sind.
Ihr zweites und schwerwiegenderes Problem ist, dass bei einem Element, das das nächste Element findet, O (n) ist. Wenn die Menge nicht geändert wurde, können Sie den Index des Elements als Referenz anstelle des Zeigers beibehalten, wodurch find-next zu einer O (1) -Operation wird. Sie haben jedoch nur einen Zeiger auf das Objekt selbst und auf keinen Fall um seinen aktuellen Index im Array zu bestimmen, außer durch Scannen des gesamten "Arrays". Dies ist ein unüberwindbares Problem für Arrays. Selbst wenn Sie Einfügungen optimieren können, können Sie nichts tun, um die Suche nach dem nächsten Typ zu optimieren.
quelle
In einem Array haben Sie das Recht, in O (1) -Zeit auf jedes Element zuzugreifen. Daher eignet es sich für Operationen wie die binäre Suche, die schnelle Sortierung usw. Die verknüpfte Liste eignet sich andererseits zum Löschen von Einfügungen, da sie in O (1) -Zeit angezeigt wird. Beides hat sowohl Vor- als auch Nachteile. Wenn Sie eines dem anderen vorziehen, kommt es darauf an, was Sie implementieren möchten.
- Die größere Frage ist, ob wir eine Mischung aus beiden haben können. So etwas wie das, was Python und Perl als Listen implementieren.
quelle
Verknüpfte Liste
Es ist vorzuziehen, wenn es um das Einfügen geht! Grundsätzlich handelt es sich um den Zeiger
1 -> 3 -> 4
Einfügen (2)
1 ........ 3 ...... 4
..... 2
Schließlich
1 -> 2 -> 3 -> 4
Ein Pfeil von den 2 Punkten bei 3 und der Pfeil von 1 Punkten bei 2
Einfach!
Aber von Array
| 1 | 3 | 4 |
Einfügen (2) | 1 | 3 | | 4 | | 1 | | 3 | 4 | | 1 | 2 | 3 | 4 |
Nun, jeder kann sich den Unterschied vorstellen! Nur für 4 Index führen wir 3 Schritte aus
Was ist, wenn die Array-Länge dann eine Million beträgt? Ist das Array effizient? Die Antwort ist nein! :) :)
Das gleiche gilt für das Löschen! In der verknüpften Liste können wir einfach den Zeiger verwenden und das Element und das nächste Element in der Objektklasse aufheben! Aber für das Array müssen wir shiftLeft () ausführen
Hoffentlich hilft das! :) :)
quelle
Verknüpfte Listen sind eher ein zu pflegender Aufwand als ein Array. Außerdem ist zusätzlicher Speicher erforderlich. Alle diese Punkte sind vereinbart. Aber es gibt ein paar Dinge, die Array nicht kann. Angenommen, Sie möchten ein Array mit einer Länge von 10 ^ 9, können Sie es nicht erhalten, da ein kontinuierlicher Speicherort vorhanden sein muss. Verknüpfte Liste könnte hier ein Retter sein.
Angenommen, Sie möchten mehrere Dinge mit Daten speichern, dann können sie einfach in der verknüpften Liste erweitert werden.
STL-Container haben normalerweise eine Implementierung einer verknüpften Liste hinter den Kulissen.
quelle
1- Die verknüpfte Liste ist eine dynamische Datenstruktur, die zur Laufzeit durch Zuweisen und Freigeben von Speicher vergrößert und verkleinert werden kann. Es ist also nicht erforderlich, eine anfängliche Größe der verknüpften Liste anzugeben. Das Einfügen und Löschen von Knoten ist wirklich einfacher.
2 Die Größe der verknüpften Liste kann zur Laufzeit zunehmen oder abnehmen, sodass keine Speicherverschwendung auftritt. Im Fall des Arrays entsteht viel Speicherplatz. Wenn wir beispielsweise ein Array der Größe 10 deklarieren und nur 6 Elemente darin speichern, wird Platz für 4 Elemente verschwendet. In der verknüpften Liste gibt es kein solches Problem, da der Speicher nur bei Bedarf zugewiesen wird.
3- Datenstrukturen wie Stapel und Warteschlangen können mithilfe einer verknüpften Liste einfach implementiert werden.
quelle
Der einzige Grund für die Verwendung der verknüpften Liste besteht darin, dass das Einfügen des Elements einfach ist (auch das Entfernen).
Ein Nachteil könnte sein, dass Zeiger viel Platz beanspruchen.
Und darüber ist die Codierung schwieriger: Normalerweise benötigen Sie keine Code-verknüpfte Liste (oder nur einmal), sie sind in STL enthalten, und es ist nicht so kompliziert, wenn Sie dies noch tun müssen.
quelle
Ich denke auch, dass die Linkliste besser ist als Arrays. weil wir in der Linkliste, aber nicht in Arrays durchlaufen
quelle
Abhängig von Ihrer Sprache können einige dieser Nachteile und Vorteile berücksichtigt werden:
C Programmiersprache : Bei Verwendung einer verknüpften Liste (normalerweise über Strukturzeiger) muss besonders berücksichtigt werden, dass kein Speicher verloren geht. Wie bereits erwähnt, lassen sich verknüpfte Listen leicht mischen, da nur Zeiger geändert werden. Werden wir uns jedoch daran erinnern, alles freizugeben?
Java : Java verfügt über eine automatische Speicherbereinigung, sodass Speicherverluste kein Problem darstellen. Dem Programmierer auf hoher Ebene sind jedoch die Implementierungsdetails einer verknüpften Liste verborgen. Methoden wie das Entfernen eines Knotens aus der Mitte der Liste sind komplizierter als es einige Benutzer der Sprache erwarten würden.
quelle
Warum eine verknüpfte Liste über ein Array? Wie einige bereits gesagt haben, höhere Geschwindigkeit beim Einfügen und Löschen.
Aber vielleicht müssen wir nicht mit den Grenzen von beidem leben und gleichzeitig das Beste aus beiden herausholen ... wie?
Beim Löschen von Arrays können Sie ein Byte "Gelöscht" verwenden, um die Tatsache darzustellen, dass eine Zeile gelöscht wurde. Daher ist eine Neuordnung des Arrays nicht mehr erforderlich. Verwenden Sie dazu eine verknüpfte Liste, um das Einfügen oder das schnelle Ändern von Daten zu erleichtern. Wenn Sie sich dann auf sie beziehen, lassen Sie Ihre Logik zuerst eine und dann die andere suchen. Wenn Sie sie also in Kombination verwenden, erhalten Sie das Beste von beiden.
Wenn Sie ein wirklich großes Array haben, können Sie es mit einem anderen, viel kleineren Array oder einer verknüpften Liste kombinieren, in der das kleinere die 20, 50, 100 zuletzt verwendeten Elemente enthält. Wenn sich das benötigte nicht in der kürzeren verknüpften Liste oder im kürzeren Array befindet, wechseln Sie zum großen Array. Wenn es dort gefunden wird, können Sie es dann zu der kleineren verknüpften Liste / dem kleineren Array hinzufügen, unter der Annahme, dass "zuletzt verwendete Elemente am wahrscheinlichsten wiederverwendet werden können" (und ja, möglicherweise das zuletzt verwendete Element aus der Liste stößt). Was in vielen Fällen zutrifft und ein Problem gelöst hat, das ich in einem .ASP-Modul zur Überprüfung von Sicherheitsberechtigungen mit Leichtigkeit, Eleganz und beeindruckender Geschwindigkeit angehen musste.
quelle
Während viele von Ihnen wichtige Adv./dis der verknüpften Liste gegen Array angesprochen haben, sind die meisten Vergleiche, wie einer besser / schlechter als der andere ist. Sie können im Array wahlfrei zugreifen, in verknüpften Listen und anderen jedoch nicht. Dies setzt jedoch voraus, dass Linklisten und Arrays in einer ähnlichen Anwendung angewendet werden. Eine richtige Antwort sollte jedoch sein, wie die Linkliste in einer bestimmten Anwendungsbereitstellung dem Array vorgezogen wird und umgekehrt. Angenommen, Sie möchten eine Wörterbuchanwendung implementieren. Was würden Sie verwenden? Array: mmm, es würde ein einfaches Abrufen durch binäre Suche und andere Suchalarme ermöglichen. Aber lassen Sie uns überlegen, wie die Linkliste besser sein kann. Sagen Sie, Sie möchten "Blob" im Wörterbuch suchen. Wäre es sinnvoll, eine Linkliste von A-> B-> C-> D ----> zu haben?
Ist der obige Ansatz nun besser oder eine flache Anordnung von [Adam, Apfel, Banane, Klecks, Katze, Höhle]? Wäre es mit Array überhaupt möglich? Ein Hauptvorteil der Linkliste besteht also darin, dass ein Element nicht nur auf das nächste Element verweist, sondern auch auf eine andere Linkliste / ein Array / einen Heap / oder einen anderen Speicherort. Array ist ein flacher zusammenhängender Speicher, der in die Blockgröße des Elements unterteilt ist, das gespeichert werden soll. Die Linkliste besteht dagegen aus nicht zusammenhängenden Speichereinheiten (kann beliebig groß sein und alles speichern) und zeigt auf jedes Element andere wie du willst. Angenommen, Sie erstellen ein USB-Laufwerk. Möchten Sie nun, dass Dateien als Array oder als Linkliste gespeichert werden? Ich denke du bekommst die Idee worauf ich zeige :)
quelle