TGViewer
C/C++ | Вопросы собесов C/C++ | Вопросы собесов @easy_c_plus · 4.19K subscribers
Post #2454 511
🤔 В какой момент принимается решение, что хеш таблице надо перестроиться?

Решение о необходимости перестроения (рехеширования) хэш-таблицы принимается на основе значения нагрузки (load factor). Нагрузка — это отношение количества элементов в хэш-таблице к количеству бакетов (размеру массива).

🚩Порог нагрузки

Для каждой хэш-таблицы обычно определяется пороговое значение нагрузки. Когда фактическая нагрузка превышает это пороговое значение, происходит рехеширование.

Формула нагрузки:
\text{load factor} = \frac{\text{number of elements}}{\text{size of table}} 


Типичные пороговые значения: Пороговое значение нагрузки часто устанавливается в пределах от 0.5 до 1.0, в зависимости от реализации. Например, std::unordered_map в стандартной библиотеке C++ по умолчанию использует пороговое значение 1.0.

🚩Процесс рехеширования

1⃣Увеличение размера таблицы
Размер массива увеличивается, часто в два раза.

2⃣Перераспределение элементов
Все существующие элементы перераспределяются в новую таблицу с использованием новой хэш-функции или той же хэш-функции, но с новым размером таблицы.

🚩Пример

#include <iostream>
#include <list>
#include <vector>

class HashTable {
private:
int currentSize;
int numberOfElements;
double loadFactorThreshold;
std::vector<std::list<std::pair<int, std::string>>> table;

void rehash() {
int oldSize = currentSize;
currentSize *= 2; // Увеличиваем размер таблицы
std::vector<std::list<std::pair<int, std::string>>> newTable(currentSize);

for (const auto& list : table) {
for (const auto& pair : list) {
int hashValue = pair.first % currentSize;
newTable[hashValue].emplace_back(pair.first, pair.second);
}
}

table = std::move(newTable);
}

public:
HashTable(int size = 10, double threshold = 0.75)
: currentSize(size), numberOfElements(0), loadFactorThreshold(threshold) {
table.resize(currentSize);
}

int hashFunction(int key) {
return key % currentSize;
}

void insertItem(int key, std::string value) {
int hashValue = hashFunction(key);
table[hashValue].emplace_back(key, value);
numberOfElements++;

// Проверяем, нужно ли выполнять рехеширование
if (static_cast<double>(numberOfElements) / currentSize > loadFactorThreshold) {
rehash();
}
}

void displayTable() {
for (int i = 0; i < currentSize; i++) {
if (!table[i].empty()) {
std::cout << "Bucket " << i << ": ";
for (auto& pair : table[i]) {
std::cout << "[" << pair.first << ": " << pair.second << "] ";
}
std::cout << std::endl;
}
}
}
};

int main() {
HashTable ht;
ht.insertItem(1, "one");
ht.insertItem(2, "two");
ht.insertItem(11, "eleven"); // Триггер рехеширования при необходимости

ht.displayTable();
// Вывод:
// Bucket 1: [1: one]
// Bucket 2: [2: two]
// Bucket 11: [11: eleven]

return 0;
}


🚩Когда происходит

Рехеширование обычно инициируется в момент, когда после добавления нового элемента нагрузка превышает установленное пороговое значение. Это гарантирует, что хэш-таблица будет эффективно обрабатывать операции поиска, вставки и удаления, поддерживая амортизированное постоянное время для этих операций.

Ставь 👍 и забирай 📚 Базу знаний
More from @easy_c_plus
  1. Oct 10, 2026🤔 Зачем нужен виртуальный деструктор? Виртуальный деструктор необходим, когда класс предп…
  2. Oct 10, 2026🤔 Что знаешь про гарантии безопасности исключений? Гарантии безопасности исключений (Exce…
  3. Oct 9, 2026🤔 Строгая гарантия безопасности Гарантии безопасности исключений в C++ делятся на три уро…
  4. Oct 8, 2026🤔 Выбрасывание исключения из конструктора — это нормально? Да, выбрасывание исключения из…
  5. Oct 8, 2026🤔 Какое преимущество у list перед vector? List обеспечивает быстрые вставки и удаления за…
  6. Oct 7, 2026🤔 Как работает priority_queue? priority_queue управляет элементами на основе их приоритет…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →