Рубрики
Без рубрики

Структуры данных 101: связанные списки

Кевин Тюреей Как и стеки и очереди, связанные списки являются формой последовательной коллекции. Это не должно быть в порядке. Связанный список состоит из независимых узлов, которые могут содержать любой тип данных. Каждый узел имеет ссылку на следующий узел в

Автор оригинала: FreeCodeCamp Community Member.

Кевин Тюреей

Как Стеки и очереди Связанные списки являются формой последовательной коллекции. Это не должно быть в порядке. Связанный список состоит из независимых узлов, которые могут содержать любой тип данных. Каждый узел имеет ссылку на следующий узел в ссылке.

Мы можем эмулировать стеки и очереди со связанными списками. Мы также можем использовать его в качестве базы для создания или увеличения других структур данных. С помощью связанных списков наши основные проблемы составляют Быстрые вставки и удаления, которые являются более эффективными для массивов.

Строительный блок этой структуры является узлом.

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

Наш узел построен с двумя свойствами, A ценность держать данные, а Следующий , ссылка изначально установлена на NULL. Следующий Свойство используется для «точки» на следующий узел в ссылке. Одним из недостатков связанных списков является то, что каждая ссылка требует большая накладная память, чем массив.

Реализация

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;  }};

На нашем втором конструкторе мы тестируем на значение для обеспечения первого узла. Если true, мы продолжаем создать новый узел со значением, пройденным и устанавливаю голову в хвост изначально.

Вставка

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;};

Для этого метода мы создаем новый узел и отрегулируйте ссылки. Предыдущая следующая ссылка оригинального узла теперь направлена на Newnode. Следующая ссылка Newnode «указана» к тому, к чему следует относиться к предыдущему узлу. Наконец, мы проверяем и сбросьте свойство хвоста.

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;};

Вставка в начале или конец связанного списка – это быстро, работает в постоянном времени. Для этого мы создаем новый узел со значением и переставьте наши ссылочные переменные. Мы сбрасываем узел, который сейчас является головой с inserthead или хвост с appendtotail Отказ

Эти операции представляют собой быстрые вставки для коллекций, толкают для стеков и enqueue для очередей. Может быть, это может прийти в голову, что беззифт для массивов одинаково. Нет, потому что с непримещением все члены коллекции должны быть перемещены один индекс. Это делает его линейной работой.

Удаление

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;};

Начиная с теста на узел для удаления, мы продолжаем регулировать ссылки. Дереференция Удаленный и устанавливая его на ноль важно. Это освобождает память и позволяет избежать нескольких ссылок на тот же объект.

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

Удаление головы и указанного узла в, Removaveter, являются постоянными во время удаления. Кроме того, если значение хвоста известно, то удаление хвоста можно сделать в O (1). Иначе мы должны двигаться линейно до конца, чтобы удалить его, O (n);

Петли и Foreach

Мы используем следующее для итерации через связанный список или для работы в каждом значении узла.

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(', ');};

Основным преимуществом связанных списков является быстрые вставки и удаления без переходных элементов или перераспределения пространства. Когда мы используем массив, пространство памяти смещается, что означает, что мы держим все это вместе. С помощью связанных списков мы можем иметь пространства памяти повсюду, нерешительное хранилище через использование ссылок. Для массивов, эта местность ссылок означает, что массивы имеют лучшую кэширование значений для более быстрого поиска. С соединенными списками кэширование не оптимизировано, и время доступа занимает дольше.

Другим аспектом связанных списков является разные типы конфигурации. Два основных примера являются круговидно Связанные, где хвост имеет ссылку на голову и голову к хвосту. Вдвойне Связанные это когда, в дополнение к узлу, имеющему ссылку на следующий узел, также имеет ссылку, оглядываясь назад на предыдущий узел.

Сложность времени

Вставка

  • Inserthead, AppendTotail – O (1)
  • Если конкретный узел известен, Ibsafter – O (1)

Удаление

  • Удалить головы – O (1);
  • Если конкретный узел известен, восстановление – O (1)
  • Если узел не известен – o (n)

Прохождение

  • Findnode, Foreach, Print – O (n)

Ресурсы

Местонаправленная ссылка Отличные ответы здесь А вот Связанный список

Спасибо за прочтение. Для практики попробуйте реализовать стек или очередь со связным списком или хранить массивы в каждом узле и извлечь данные. Спросите себя, когда я доберусь до массива, это, на самом деле, лучший выбор для моих потребностей?

Оригинал: “https://www.freecodecamp.org/news/data-structures-101-linked-lists-254c82cf5883/”