Ваша хеш-таблица работает следующим образом: у вас есть bins
корзин, и каждая корзина представляет собой связанный список пар ключ / значение.Все элементы в корзине имеют одинаковый хэш-код по модулю количества корзин.
Возможно, вы создали таблицу бинов, когда создали или инициализировали хэш-таблицу, что-то вроде этого:
table->table = malloc(table->bins * sizeof(*table->table);
for (size_t i = 0; i < table->bins; i++) table->table[i] = NULL;
Теперь, почему элемент table
имеет две звезды?
- «Внутренняя» звезда означает, что таблица хранит указатели на узлы, а не на сами узлы.
«Внешний» запуск - это указатель на выделенную память.Если бы ваша хеш-таблица имела фиксированный размер, например всегда с 256 бинами, вы можете определить ее следующим образом:
struct node_s *table[256];
Если вы передадите этот массив, он станет (или «распадется на»)указатель на его первый элемент, struct node_s **
, точно так же, как массив, полученный из malloc
.
- Вы получаете доступ к содержимому l´bins через связанные списки и заголовок связанного списка
i
- это table->table[i]
.
У вашего кода другие проблемы:
Чего вы хотели достичь с помощью (table->table)++
?Это сделает дескриптор выделенной памяти не первым элементом, а следующим.После выполнения этого времени хеш-памяти *table->table
теперь будет на правильном узле, но вы потеряете исходный дескриптор, который вы должны сохранить, потому что вы должны передать его free
позже, когда очистите свою хеш-таблицу.Не теряйте ручку для выделенной памяти!Вместо этого используйте другой локальный указатель.
Вы создаете локальный узел n
, а затем делаете ссылку в своем связанном списке с указателем на этот узел.Но узел n
исчезнет после того, как вы выйдете из функции, и ссылка будет «устаревшей»: она будет указывать на недействительную память.Вы также должны создать память для узла с malloc
.
. Простая реализация вашей таблицы has может быть такой:
void set(hash_t table, char *key, int value)
{
unsigned int hashnum = hash(key) % table->bins;
// create (uninitialised) new node
struct node_s *nnew = malloc(sizeof(*nnew));
// initialise new node, point it to old head
nnew->key = strdup(key);
nnew->value = value;
nnew->link = table->table[hashnum];
// make the new node the new head
table->table[hashnum] = nnew;
}
Это делает новый узелглава связанного списка.Это не идеально, потому что если вы перезаписываете элементы, будут найдены новые (что хорошо), но старые все еще будут в таблице (что не хорошо).Но это, как говорится, оставлено читателю в качестве упражнения.
(Функция strdup
не является стандартной, но широко доступна. Она также создает новую память, которую вы должны освободить позже, ноэто гарантирует, что строка «живет» (все еще действует) после того, как вы завершили хеш-таблицу.)
Пожалуйста, не указывайте, сколько звездочек в коде.Если одной звезды слишком мало, она находится в hash_t
, где вы указали тип указателя.