Реализация Списка Наилучших Смежностей

#javascript #graph #hashmap #hashtable #adjacency-list

Вопрос:

Я могу реализовать список смежности либо в виде массива Связанных списков, либо в виде Карты Связанных списков (т. Е. хэш-таблица). Есть ли когда-нибудь причина использовать реализацию массива поверх реализации карты? Я спрашиваю, потому что я сталкивался со многими веб-сайтами, которые описывают реализацию массива, но очень немногие упоминают использование хэш-таблиц. Насколько я понимаю, хэш-таблицы должны превосходить массивы.

Ниже показано, как я бы закодировал список смежности на основе хэш-таблицы вместе с соответствующим кодом для вспомогательных классов.

LinkedListNode.js

 class LinkedListNode {
  constructor(value = 0, next = undefined) {
    this.value = value;
    this.next = next;
  }
}
 

LinkedList.js (удалены ненужные функции)

 class LinkedList {
  constructor(headValue = null) {
    this.head = headValue ? new LinkedListNode(headValue) : headValue;
  }

  addToTail(value) {
    const node = new LinkedListNode(value);
    if (!this.head) {
      this.head = node;
    } else {
      let pointer = this.head;
      while (pointer.next) {
        pointer = pointer.next;
      }
      pointer.next = node;
    }
  }
  
  toArray() {
    const items = [];
    let pointer = this.head;
    while (pointer) {
      items.push(pointer.value);
      pointer = pointer.next;
    }
    return items;
  }
}
 

HashTable.js — мы предполагаем, что столкновений не будет

 class HashTable {
  constructor() {
    this.items = {};
  }

  set(key, value) {
    if (this.items[key]) {
      this.items[key].addToTail(value);
    } else {
      this.items[key] = new LinkedList(value);
    }
  };

  get(key) {
    return this.items[key]; 
  }

  print() {
    const entries = Object.entries(this.items);
    for (let i = 0; i < entries.length; i  = 1) {
      const [key, list] = entries[i];
      console.log(`${key}: ${list.toArray()}`);
    }
  }
}
 

Использование

 const adjacencyList = new HashTable();
adjacencyList.set(1, 2);
adjacencyList.set(2, 4);
adjacencyList.set(3, 1);
adjacencyList.set(3, 2);
adjacencyList.set(3, 5);
adjacencyList.set(4, 6);
adjacencyList.set(5, 2);
adjacencyList.set(5, 4);
adjacencyList.set(5, 6);
adjacencyList.set(6, null);
adjacencyList.print();

// Outputs
'1: 2'
'2: 4'
'3: 1,2,5'
'4: 6'
'5: 2,4,6'
'6: '
 

Ответ №1:

Есть ли когда-нибудь причина использовать реализацию массива поверх реализации карты?

ДА:

  • когда вы знаете, сколько узлов n имеет ваш график, и
  • узлы идентифицируются целыми числами в диапазоне 0..n-1

В этом случае «хэш» — это индекс в массиве. Некоторые движки JavaScript могут создавать более быстрый код, когда вы работаете с массивами вместо обычных объектов.

ПРИМЕЧАНИЕ: это, безусловно, будет быстрее, если вы замените связанные списки массивами (и push ).

Комментарии:

1. Именно тот ответ, который я искал. Ура!