Eine Verkettete List ist eine dem Array ähnliche Datenstruktur, jedoch besteht jedes Item in der Liste aus einem Objekt mit zwei Eigenschaften:
wert
Eigenschaft, die den eigentlichen Inhalt des Knoten enthält.naechster
Eigenschaft, welche auf das nächste Objekt in der Liste verweist.The linked list data structure value
can be of any valid JavaScript data types (string, number, boolean, object, etc).
Eine verkettete Liste kann man sich als eine Serie von aufgehängten Früchtekörben vorstellen:
Bei der Analogie Früchtekorb sind die Knoten für die Aufnahme von Früchten gedacht. Eine verkettete Liste kann für alle gültigen Datentypen konzipiert werden (string, number, boolean, object etc.). Das Objektdiagramm zeigt die Idee vom Stativ, das auf den ersten Knoten zeigt und die rekursive Struktur der Knoteneigenschaft naechster, die erneut auf einen Knoten zeigt.
Die Illustration zeigt eine typische Verkettete Liste, die nur über den Zeiger erster des Objekts Stativ zugänglich ist:
Werfen wir einen Blick auf die folgende basale Verkettete Liste, welche drei Items aufweist:
Die Verkettete Liste erscheint in der Konsole als Serie von Objekten. Grafisch lässt sich diese Struktur wie folgt als am Stativ hängende Liste darstellen:
Obwohl eine Verkettete List einem Array gleicht, ist der Zugriff auf ein bestimmtes Element komplizierter und langsamer, da kein direkter Zugriff auf ein bestimmtes Element über einen Index möglich ist. Man muss die Liste vom Kopf her bis zum gewünschten Element durchlaufen. Das LIFO-Prinzip (Last in – First out) lässt sich mit dieser Art Liste jedoch bestens realisieren.
Für einen schnelleren Zugang zum letzten Element der Liste, könnte man die Stativ-Klasse mit einem zweiten Zeiger letzter ergänzen. Dies würde die Implementierung einer Warteschlage nach dem FIFO-Prinzip (First in – First out) vereinfachen.
Folgende drei Varianten von Verketteter Listen sind verbreitet:
Zirkuläre Listen können einfach oder doppelt verkettet sein.
Nun wollen wir in Etappen eine einfache, nicht zirkuläre Verkettete Liste implementieren.
Wir implementieren eine Liste nur mit einem Zeiger mit Namen erster
, eine nach dem LIFO-Prinzip funktionierende Liste. Dazu sind folgende Etappen notwendig:
stativList
inkl. Konstruktor erstelleneinfuegen
ergänzen, zum Einfügen eines Knotens auflisten
ergänzen, welche die Knoten der Reihe nach listetentfernen
erstellen, zum Löschen eines KnotenEiner Funktion wird der Inhalt für den Knoten übergeben und die Funktion liefert ein Knotenobjekt mit dem erwünschten naechster
(Inhalt) und einem leeren Zeiger naechster
zurück.
function erstelleKnoten(farbe) {
return {
wert: farbe,
naechster: null
};
}
Jedes Mal wenn ein neuer Knoten erwünscht ist, kann nun die Funktion erstelleKnoten()
aufgerufen werden:
let neuerKnoten = erstelleKnoten(8);
console.log(neuerKnoten);
// { wert: 8, naechster: null }
Nun schreiben wir die stativLink
Klasse mit passendem Konstruktor:
class stativList {
constructor() {
this.erster = null;
}
}
Eine neue Instanz vom Typ stativLink
weist nur eine einzige Eigenschaft erster
auf, die zu Beginn den Wert null
besitzt. Sobald ein erster Knoten eingefügt ist, soll erster
auf diesen Knoten der Verketteten Liste zeigen.
Die Methode einfuegen
soll einen einzigen Parameter entgegennehmen, den Wert für den Knoten. Die Syntax der Funktion sieht wie folgt aus:
einfuegen(farbeNr) {
let neuerKnoten = erstelleKnoten(farbeNr);
neuerKnoten.naechster = this.erster;
this.erster = neuerKnoten;
}
Die Funktion erstellt einen neuen Knoten und weist der Eigenschaft naechster
den bisherigen Inhalt des Zeigers erster
der Verketteten Liste zu. Anschliessend wird der Zeiger erster
auf neuerKnoten
gesetzt. Damit ist das Einfügen an erster Stelle der Liste geglückt. Die zentralen Schritte sind in der folgenden Darstellung gezeigt:
Um die in der Verketteten Liste vorhandenen Knoten anzuzeigen, ergänzen wir die Methode auflisten
. Diese startet beim ersten Knoten und geht die Liste vom ersten bis zum letzten Element durch. Die while
-Schleife hangelt von einem Knoten zu nächsten, bis der Knoten gleich null
ist. In der Schleife wird von jedem Knoten sein wert
ausgegeben und dem aktuellen Knoten der Knoten aus der Eigenschaft naechster
zugewiesen.
auflisten() {
let aktueller = this.erster;
while (aktueller != null) {
console.log("farbNr: " + aktueller.wert) ;
aktueller = aktueller.naechster;
}
console.log("========");
}
Nun fügen wir mit einfuegen
einige Knoten in die Liste ein und lassen zur Kontrolle an zwei Stellen die Verkettete Liste mit Hilfe der Methode auflisten
anzeigen:
const meineListe = new stativList();
meineListe.einfuegen(0);
meineListe.einfuegen(1);
meineListe.auflisten();
meineListe.einfuegen(2);
meineListe.einfuegen(3);
meineListe.einfuegen(4);
meineListe.auflisten();
Zuerst muss die entfernen
Methode überprüfen, ob der Zeiger erster
nicht auf null
zeigt. In diesem Fall wäre die Liste leer und der Versuch einen Knoten zu löschen unsinnig.
Die Schritte um den ersten Knoten zu entfernen sind:
erster
identifizierterster
der Liste muss nun auf den in der Eigenschaft naechster
definierten Knoten zeigen.Die beiden zentralen Schritte des Löschens sind in der Darstellung ersichtlich:
Hier der Code der Methode entferne
:
entferne() {
if (this.erster != null) {
let ersterKnoten = this.erster;
this.erster = ersterKnoten.naechster;
return ersterKnoten;
}
}
Nun können Knoten entfernt und die Wirkung in der Konsole mit Hilfe der Methode auflisten
überprüft werden:
meineListe.entferne();
meineListe.entferne();
meineListe.auflisten();
Um die Liste grafisch auf dem Canvas darzustellen, soll der Code mit der p5js-Systemfunktion setup erweitert werden. Dabei gilt es folgende Punkte zu beachten:
erstelleKnoten
und die Klasse stativList
sind global zu definieren.meineListe
ist ebenfalls ausserhalb der Systemfunktion als Konstante zu deklarieren.setup
ist ein Canvas von 200 px mal 800 px zu kreieren.setup
der Liste zugefügt werden.Die ergänzte setup
-Funktion präsentiert sich wie folgt:
// Instanz der Klasse stativList erstellen
const meineListe = new stativList();
function setup() {
createCanvas(200, 800);
textAlign(CENTER);
textSize(44);
background(240);
colorMode(HSB, 12, 100, 100);
// ...
}
Dabei verweisen die Auslassungszeichen auf die Befehle zum einfügen, entfernen und auflisten der Knoten hin.
Nun kann der Klasse stativList
eine weitere Methode zeichne
eingefügt werden. Diese funktioniert der Methode auflisten
ähnlich: statt bei jedem Knoten den Wert auszugeben, wird ein circle
mit dem Wert entsprechender Farbe ausgegeben. Dies lässt sich z.B. mit colorMode(HSB, 18,100,100)
einfach realisieren. Dann entsprechen die Werte den 18 definierten HSB-Farbwerten:
zeichne() {
let aktueller = this.erster;
let aktY = 30;
while (aktueller != null) {
fill(aktueller.wert, 100, 100);
circle(100, aktY, 60);
aktY = aktY + 60;
aktueller = aktueller.naechster;
}
}
Das Ergebnis der Methode zeichne
präsentiert sich auf dem Canvas wie folgt: