Я изо всех сил пытался понять, как это работает некоторое время в GDB, но мне трудно понять это. В основном есть массив (elements_
), в которые хэшируются вещи, они являются указателями на структуры, содержащие определенные крючки, используемые для цепочки. Вот пример структуры:
struct foo
{
Data data;
foo* next;
foo** prevNext;
};
затем создается хеш-таблица с
HashTable<foo> hash;
и это функция вставки выглядит следующим образом (я пропустил изменение размера и все для простоты)
template <class T>
void HashTable<T>::insert(T* x)
{
int bucket = hashFunc(x->data);
T** xPtr = &elements_[bucket];
x->next = *xPtr;
x->prevNext = xPtr;
if (x->next)
x->next->prevNext = &x->next;
*xPtr = x;
}
и удаление заключается в следующем
template<class T>
void HashTable<T>::remove(T* x)
{
if (x->next)
x->next->prevNext = x->prevNext;
*x->prevNext = x->next;
}
И для справки, как это искать, это так:
template<class T>
T* HashTable<T>::find(Data& data)
{
int bucket = hashFunc(data);
T* ptr = elements_[bucket];
while (ptr != 0)
{
if(ptr->data == data)
return ptr;
ptr = ptr->next;
}
return 0;
}
Я продолжаю пытаться следить за вставкой 2-3 сталкивающихся элементов (для начала установив небольшой размер таблицы) и удалениями, чтобы увидеть, что такое логика, но я не понимаю ее. Вот диаграмма того, что я думаю, что делает операция удаления (удаление узла 2), хотя это все еще немного размыто в моей голове:
Элементы, попадающие в одно и то же ведро, хранятся в виде двусвязного списка (вроде).
Lookup обходит этот список, пока не найдет элемент с соответствующим data
значение.
Других решений пока нет …