de Kevin Turney

Ca stive și cozi, Listele legate sunt o formă a unei colecții secvențiale. Nu trebuie să fie în ordine. O listă legată este alcătuită din noduri independente care pot conține orice tip de date. Fiecare nod are o referință la următorul nod din link.

Structuri de date 101 Liste legate

Putem emula stive și cozi cu liste legate. La fel de bine îl putem folosi ca bază pentru a crea sau a mări alte structuri de date. Cu listele conectate, preocupările noastre principale sunt cu inserții și ștergeri rapide, care sunt mai performante peste matrice.

Blocul de construcție al acestei structuri este un nod.

const Node = function(value) {  this.value = value;  this.next = null;};

Nodul nostru este construit cu două proprietăți, a value să dețină date și next, o referință setată inițial la nul. next proprietatea este utilizată pentru a „indica” următorul nod din legătură. Unul dintre dezavantajele listelor legate este că fiecare referință necesită o memorie mai mare decât o matrice.

Implementare

const LinkedList = function(headvalue) {  // !! coerces a value to a Boolean  if (!!headvalue) {    return "Must provide an initial value for the first node"  } else {    this._head = new Node(headvalue);    this._tail = this.head;  }};

În cel de-al doilea constructor, testăm o valoare pentru a furniza primul nod. Dacă este adevărat, continuăm să creăm un nou nod cu valoarea trecută și setăm capul la coadă inițial.

Inserare

LinkedList.prototype.insertAfter = function(node, value) {  let newNode = new Node(value);  let oldNext = node.next;  newNode.next = oldNext;  node.next = newNode;  if (this._tail === node) {    this._tail = newNode;  }  return newNode;};

Pentru această metodă, creăm un nou nod și ajustăm referințele. Fosta următoare referință a nodului original este acum îndreptată către newNode. Următoarea referință a noului nod este „indicată” la ce se referea următorul nod anterior. În cele din urmă, verificăm și resetăm proprietatea coadă.

LinkedList.prototype.insertHead = function(value) {  let newHead = new Node(value);  let oldHead = this._head  newHead.next = oldHead;  this._head = newHead;  return this._head;};
LinkedList.prototype.appendToTail = function(value) {  let newTail = new Node(value);  this._tail.next = newTail;  this._tail = newTail;  return this._tail;};

Inserarea la începutul sau la sfârșitul unei liste conectate este rapidă, funcționând în timp constant. Pentru aceasta, creăm un nou nod cu o valoare și rearanjăm variabilele noastre de referință. Resetăm nodul care este acum capul cu insertHead sau coada cu appendToTail.

Aceste operații reprezintă inserții rapide pentru colecții, împingere pentru stive și coadă pentru cozi. S-ar putea să vă vină în minte că neschimbarea pentru matrice este aceeași. Nu, pentru că, cu unshift, toți membrii colecției trebuie să fie mutați cu un singur index. Acest lucru îl face o operație liniară în timp.

Ștergere

LinkedList.prototype.removeAfter = function(node) {  let removedNode = node.next;  if (!!removedNode) {    return "Nothing to remove"  } else {    let newNext = removedNode.next    node.next = newNext;    removedNode.next = null; // dereference to null to free up memory    if (this._tail === removedNode) {      this._tail = node;    }  }  return removedNode;};

Începând cu un test pentru eliminarea unui nod, procedăm la ajustarea referințelor. Diferențierea removedNode iar setarea la nul este importantă. Acest lucru eliberează memoria și evită să aibă mai multe referințe la același obiect.

LinkedList.prototype.removeHead = function() {  let oldHead = this._head;  let newHead = this._head.next;  this._head = newHead;  oldHead.next = null;  return this._head;};

Ștergerea unui cap și a unui nod specificat în, removeAfter, sunt îndepărtări constante de timp. În plus, dacă se cunoaște valoarea cozii, atunci îndepărtarea cozii se poate face în O (1). Altfel, trebuie să ne deplasăm liniar până la capăt pentru al elimina, O (N);

Buclă și pentru fiecare

Folosim următoarele pentru a itera printr-o listă legată sau pentru a opera pe fiecare valoare a nodului.

LinkedList.prototype.findNode = function(value) {  let node = this._head;  while(node) {    if (node.value === value) {      return node;    }    node = node.next;  }  return `No node with ${value} found`;};
LinkedList.prototype.forEach = function(callback) {  let node = this._head;  while(node) {    callback(node.value);    node = node.next;  }};
LinkedList.prototype.print = function() {  let results = [];  this.forEach(function(value) {    result.push(value);  });  return result.join(', ');};
1611007505 318 Structuri de date 101 Liste legate

Principalul avantaj al Listelor conectate este inserarea și ștergerea rapidă fără a rearanja elementele sau realocarea spațiului. Când folosim o matrice, spațiul de memorie este contigu, adică îl păstrăm pe toate împreună. Cu listele legate, putem avea spații de memorie peste tot, stocare necontiguă prin utilizarea de referințe. Pentru tablouri, acea localitate de referințe înseamnă că tablourile au o mai bună stocare în cache a valorilor pentru o căutare mai rapidă. Cu listele conectate, stocarea în cache nu este optimizată, iar timpul de acces durează mai mult.

Un alt aspect al listelor legate este diferitele tipuri de configurație. Două exemple primare sunt circular legat, unde coada are o referință la cap și capul la coadă. De două ori legat este atunci când, pe lângă nodul care are o referință la nodul următor, are și o referință privind înapoi la nodul anterior.

Complexitatea timpului

Inserare

  • insertHead, appendToTail – O (1)
  • dacă este cunoscut un anumit nod, insertAfter – O (1)

Ștergere

  • removeHead – O (1);
  • dacă este cunoscut un anumit nod, removeAfter – O (1)
  • dacă nodul nu este cunoscut – O (N)

Traversare

  • findNode, forEach, print – O (N)

Resurse

Localitatea de referință
Răspunsuri grozave aici
si aici
Listă legată

Mulțumesc pentru lectură. Pentru practică, încercați să implementați o stivă sau o coadă cu o listă legată sau să stocați tablouri în fiecare nod și extrageți date. Întrebați-vă când ajung la o gamă, este, de fapt, cea mai bună alegere pentru nevoile mele?