Я ищу для структуры данных hash table
, которая не требует rehash
для расширения и усадки? Rehash - это процессорное усилие. Мне было интересно, можно ли создать структуру данных хеш-таблицы таким образом, чтобы не требовать перефразирования? Вы слышали о такой структуре данных раньше?Развернуть хеш-таблицу без перефразирования?
ответ
Это зависит от того, чего вы хотите избежать. Rehashing подразумевает пересчет хэш-значений. Вы можете избежать этого, сохранив хэш-значения в структурах хэша. Повторная сортировка записей в перераспределенной хеш-таблице может быть менее дорогостоящей (как правило, одной процедурой по модулю или маскировке) и вряд ли можно избежать для простых реализаций хэш-таблицы.
Предполагая, что вам действительно нужно это .. Это возможно. Здесь я приведу тривиальный пример, на котором вы можете построить.
// Basic types we deal with
typedef uint32_t key_t;
typedef void * value_t;
typedef struct
{
key_t key;
value_t value;
} hash_table_entry_t;
typedef struct
{
uint32_t initialSize;
uint32_t size; // current max entries
uint32_t count; // current filled entries
hash_table_entry_t *entries;
} hash_table_t;
// Hash function depends on the size of the table
key_t hash(value_t value, uint32_t size)
{
// Simple hash function that just does modulo hash table size;
return *(key_t*)&value % size;
}
void init(hash_table_t *pTable, uint32_t initialSize)
{
pTable->initialSize = initialSize;
pTable->size = initialSize;
pTable->count = 0;
pTable->entries = malloc(pTable->size * sizeof(*pTable->entries));
/// @todo handle null return;
// Set to ~0 to signal invalid keys.
memset(pTable->entries, ~0, pTable->size * sizeof(*pTable->entries));
}
void insert(hash_table_t *pTable, value_t val)
{
key_t key = hash(val, pTable->size);
for (key_t i = key; i != (key-1); i=(i+1)%pTable->size)
{
if (pTable->entries[i].key == ~0)
{
pTable->entries[i].key = key;
pTable->entries[i].value = val;
pTable->count++;
break;
}
}
// Expand when 50% full
if (pTable->count > pTable->size/2)
{
pTable->size *= 2;
pTable->entries = realloc(pTable->entries, pTable->size * sizeof(*pTable->entries));
/// @todo handle null return;
memset(pTable->entries + pTable->size/2, ~0, pTable->size * sizeof(*pTable->entries));
}
}
_Bool contains(hash_table_t *pTable, value_t val)
{
// Try current size first
uint32_t sizeToTry = pTable->size;
do
{
key_t key = hash(val, sizeToTry);
for (key_t i = key; i != (key-1); i=(i+1)%pTable->size)
{
if (pTable->entries[i].key == ~0)
break;
if (pTable->entries[i].key == key && pTable->entries[i].value == val)
return true;
}
// Try all previous sizes we had. Only report failure if found for none.
sizeToTry /= 2;
} while (sizeToTry != pTable->initialSize);
return false;
}
Идея состоит в том, что функция хеша зависит от размера таблицы. Когда вы меняете размер таблицы, вы не переделываете текущие записи. Вы добавляете новые с новой хэш-функцией. При чтении записей вы пытаетесь использовать все хеш-функции, которые когда-либо использовались в этой таблице.
Таким образом, get()
/ и подобные операции занимают больше времени, чем больше раз, чем вы расширили свой стол, но у вас нет огромного всплеска перефразирования. Я могу представить некоторые системы, где это было бы требованием.
не требует переоборудования для расширения и усадки? Rehash - это процессорное усилие. Мне было интересно, можно ли создать структуру данных хеш-таблицы таким образом, чтобы не требовать перефразирования? Вы слышали о такой структуре данных раньше?
Это зависит от того, что вы называете «перепев»:
Если вы просто означает, что перепев на уровне таблицы не должны повторно использовать хэш-функции для каждого ключа при изменении размера, то это легко с большинство библиотек: например оберните ключ и его исходное значение хэш-значения (pre-modulo-table-size) вместе a la
struct X { size_t hash_; Key key_ };
, поставьте библиотеку хэш-таблицы с хеш-функцией, которая возвращаетhash_
, но сравнивает функцию, которая сравниваетkey_
s (в зависимости от сложностиkey_
сравните, вы можете использоватьhash_
для оптимизации, напримерlhs.hash_ == rhs.hash_ && lhs.key_ == rhs.key_
).- Это поможет большинству, если хэширование ключей было особенно трудоемким (например, криптографическая сила на длинных клавишах). Для очень простого хэширования (например, пересылка
int
с) это замедлит вас и потеряет память.
- Это поможет большинству, если хэширование ключей было особенно трудоемким (например, криптографическая сила на длинных клавишах). Для очень простого хэширования (например, пересылка
Если вы имеете в виду операцию на уровне таблицы увеличения или уменьшения памяти для хранения и переиндексации все сохраненные значения, то да - можно избежать - но для этого вы должны коренным образом изменить способ хэш-таблица работы , и нормальный профиль производительности. Обсуждалось ниже.
Как только один пример, вы могли бы использовать более типичный хеш реализации (назовем его Н), имея свой собственный хэш-таблицу (C) имеют H** p
, что - до начального предела размера - будет иметь p[0]
быть единственный экземпляр H, а также просто паромные операции/результаты.Если таблица выходит за рамки этого, вы сохраняете p[0]
, ссылаясь на существующий H, создавая вторую хэш-таблицу H, которая будет отслеживаться p[1]
. Тогда вещи начинают получать ненадежные:
для поиска или удалений в C, ваша реализации должна искать
p[1]
затемp[0]
и сообщать о любой спичке либо извставить новое значение в C, ваша реализация должна подтвердить, что это не в
p[0]
, а затем вставить вp[1]
- с каждым
insert
(и, возможно, даже для других операций), он может при необходимости перенести любые м atching - или произвольная записьp[0]
- доp[1]
так постепенноp[0]
пустые; вы можете легко гарантировать, чтоp[0]
будет пуст до того, какp[1]
будет таким полным (и, следовательно, потребуется большая таблица). Когдаp[0]
пуст, вы можете захотетьp[0] = p[1]; p[1] = NULL;
, чтобы сохранить простую ментальную модель того, что есть, - множество опций.
- с каждым
Некоторых существующих реализации хэш-таблиц является очень эффективным при переборе над элементами (например, GNU C++ std::unordered_set
), поскольку есть односвязный список всех значений, и хэш-таблица действительно только коллекция указателей (на языке C++, итераторах) в связанном списке. Это может означать, что если ваше использование падает ниже некоторого порогового значения (например, коэффициент загрузки 10%) для вашей единственной/большой хеш-таблицы, вы знаете, что можете очень эффективно перенести оставшиеся элементы на меньшую таблицу.
Эти трюки используются некоторыми хеш-таблицами, чтобы избежать внезапной тяжелой стоимости во время переигрывания, и вместо этого распределить боль более равномерно по нескольким последующим операциям, избегая, возможно, неприятного всплеска в латентности.
Некоторые из вариантов реализации имеют смысл только для открытой или закрывающей хеширующей реализации или полезны только тогда, когда ключи и/или значения малы или большие, и в зависимости от того, вставляет ли таблица их или указывает на их. Лучший способ узнать об этом - это код ....
- 1. Реализация таблицы хэшей (ошибка перефразирования области)
- 2. Какая библиотека естественного языка используется для перефразирования?
- 3. java hashmap значения ушли после перефразирования?
- 4. Развернуть изображение без сглаживания
- 5. Rangy как развернуть без символов?
- 6. Развернуть программу C# без установщика
- 7. развернуть все тумблер без щелчка
- 8. Зачем нужна HashMap для перемещения элементов во время перефразирования?
- 9. Развернуть приложение asp.net без компиляции DLL
- 10. Развернуть TableViewCell без использования дополнительной ячейки
- 11. Bootstrap Navbar Развернуть/свернуть мобильный без JavaScript
- 12. Как развернуть перекодированный сайт без потери трафика?
- 13. Развернуть Axis2 .aar без веб-приложения Axis2
- 14. Развернуть только схему куба, без обработки
- 15. Как развернуть проект Django без ткани
- 16. Развернуть макрос функций C/C++ без препроцессора
- 17. Как развернуть репозиторий без GitHub на GitHub?
- 18. Можно ли развернуть веб-приложение без компиляции?
- 19. Возможно ли развернуть SearchView без отображения клавиатуры
- 20. Как развернуть приложение iPhone (без App Store)?
- 21. Как развернуть Umbraco 7.3.1 без backoffice
- 22. Создание TextView развернуть без покрытия других видов
- 23. Развернуть раскрывающееся меню без изменения размеров контейнера
- 24. Как развернуть изменения без прерывания обслуживания?
- 25. Могу ли я развернуть приложение без манифеста?
- 26. Как развернуть скомпилированное приложение без Visual Studio?
- 27. Как развернуть сайт без уха в jboss
- 28. Развернуть сайт KeystoneJS без генератор-трафарета
- 29. Развернуть приложение AppEngine без изменения файлов GWT
- 30. Как развернуть мою службу WCF без IIS?
Подумайте о том, как хэш-таблицы работают внутри и почему они созданы так, как они есть. Как бы вы ожидали, что хеш-таблица no-rehash не будет работать? – awksp
Сохраните хэш-значение объекта с объектом и используйте многоуровневую таблицу хэша. – user3386109
Если вы беспокоитесь о паузе, вызванной копированием данных на новый HT (может быть проблематичным для систем реального времени), вы можете сделать копию постепенно, то есть сохранить как старые, так и новые элементы HT и копии время. В течение этого времени вам придется отказаться от старого HT, если поиск не сработает. Если вы хотите увеличить размер с небольшими приращениями и не копировать все данные во время этого, вы должны изучить последовательное хеширование, которое часто используется DHT. – NikiC