(Коли) є пошук хеш-таблиці O (1)?


70

Часто кажуть, що пошук хеш-таблиць працює в постійний час: ви обчислюєте значення хеша, яке дає вам індекс для пошуку масиву. І все ж це ігнорує зіткнення; в гіршому випадку кожен елемент висаджується в одне відро і час пошуку стає лінійним ( ).Θ(n)

Чи є умови в даних, які можуть зробити пошук хеш-таблиці справді ? Це лише в середньому, чи може хеш-таблиця мати найгірший варіант пошуку (1) ?O(1)O(1)

Примітка: я тут виходжу з точки зору програміста; коли я зберігаю дані в хеш-таблиці, майже завжди це рядки або деякі складові структури даних, і дані змінюються протягом життя хеш-таблиці. Тому, хоча я ціную відповіді про ідеальні хеши, вони милі, але анекдотичні та не практичні з моєї точки зору.

PS Спостереження: для яких типів є операції з хеш-таблицею O (1)?


3
Чи можете ви жити з амортизованим часом доступу ? Загалом, продуктивність хеш-таблиць буде сильно залежати від того, скільки накладних витрат для розріджених хештелів ви готові терпіти і від розподілу фактичних хеш-значень. O(1)
Рафаель

5
О, btw: ви можете уникнути лінійної поведінки в гіршому випадку, використовуючи (врівноважені) дерева пошуку замість списків.
Рафаель

1
@Raphael Мені буде дуже цікава відповідь, яка пояснює (в широких межах), коли я можу розраховувати на амортизовану та коли я не можу. Щодо розподілу хеш-значень, це насправді частина мого питання: як я можу знати? Я знаю, що хеш-функції повинні добре розподіляти значення; але якби вони завжди робили найгірший випадок, ніколи не дійшли, що не має сенсу. O(1)
Жиль

1
Також будьте уважні до передчасної оптимізації; для невеликих (декількох тисяч елементів) даних я часто бачив, що врівноважені двійкові дерева перевершують хештелі за рахунок нижчих накладних витрат (порівняння рядків набагато дешевше, ніж хеш-рядки). O(logn)
isturdy

Відповіді:


41

Є два параметри, за допомогою яких можна отримати найгірший час.O(1)

  1. Якщо ваша установка статична, то хешування FKS отримає найгірші гарантії . Але, як ви вказали, ваше налаштування не є статичним.O(1)

  2. Якщо ви використовуєте хешування зозулі, то запити та видалення - це найгірший варіант , але очікується лише вставка . Хешування зозулі працює досить добре, якщо у вас є верхня межа загальної кількості вставок, а розмір столу буде приблизно на 25% більшим.O(1)O(1)

Більше інформації тут .


3
Не могли б ви розширити FKS та зозулю? Обидва терміни для мене нові.
Жиль

1
А як щодо динамічного ідеального хешування? Він має найгірший пошук і амортизовану вставку та видалення. ( citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.30.8165 )O(1)O(1)
Joe

2
FKS - ініціали (Fredman, Komlós, Szemerédi), а зозуля - назва мосту. Він використовується для цього типу гасіння, оскільки пташенята-зозулі виштовхують яйця сибірок з гнізда. Це дещо нагадує, як функціонує цей метод хешування.
uli

1
@Suresh: Дійсно? Я думав, що вам потрібні -незалежні функції, які я завжди асоціював з необхідними розширювачами. Я стою виправлений. Трохи видалить мій коментар logn
Луї

1
Щоб зробити більш корисним коментар до цієї відповіді, як зазначає @Suresh, хешування зозулі буде добре працювати без фантазійних (і великих) хеш-функцій, які використовуються для її теоретичного аналізу.
Луї

21

Ця відповідь підсумовує частини TAoCP Vol 3, Ch 6.4.

Припустимо, у нас є набір значень , яких ми хочемо зберігати в масиві розміром . Ми використовуємо хеш-функцію ; як правило,. Ми називаємо коефіцієнт навантаження по . Тут будемо вважати природне ; У практичних сценаріях ми маємо , і нам доводиться відображати до себе.VnAmh:V[0..M)M|V|α=nmm = M m M mAm=MmMm

Перше спостереження полягає в тому, що навіть якщо має однакові характеристики¹ висока ймовірність двох значень, що мають однакове хеш-значення; це, по суті, зразок сумнозвісного парадоксу дня народження . Тому нам зазвичай доведеться мати справу з конфліктами і можемо відмовитись від сподівання на найгірший час доступу.O ( 1 )hO(1)

А як із середнім випадком? Припустимо, що кожен ключ з відбувається з однаковою ймовірністю. Середня кількість перевірених записів (успішний пошук), відповідно (невдалий пошук) залежить від використовуваного методу вирішення конфлікту.C S n C U n[0..M)CnSCnU

Прикування

Кожен запис масиву містить (вказівник на голову) пов'язаних списків. Це гарна ідея, оскільки очікувана довжина списку невелика ( ), хоча ймовірність виникнення зіткнень висока. Зрештою, отримуємо Це можна трохи покращити, зберігаючи списки (частково або повністю) всередині таблиці. C S n1+αnm

CnS1+α2 and CnU1+α22.

Лінійне зондування

При вставці (відповідно пошуку значень) перевіряйте позиції у цьому порядку до порожнього положення (відповідно ) знайдено Перевага полягає в тому, що ми працюємо локально і без вторинних структур даних; однак кількість середніх доступів розходиться для : Однак для продуктивність порівнянна з ланцюжком².v

h(v),h(v)1,,0,m1,,h(v)+1
vα1
CnS12(1+11α) and CnU12(1+(11α)2).
α<0.75

Подвійний хешинг

Подібно лінійним зондуванням , але розмір кроку пошуку управляється з допомогою другого хеш - функції , яка є взаємно просте з . Офіційне виведення не наводиться, але емпіричні спостереження говорять про те, що Цей метод був адаптований Brent; його варіант амортизує збільшені витрати на введення при дешевших пошуках.M

CnS1αln(11α) and CnU11α.

Зауважте, що видалення елементів із та розширення таблиць має різну ступінь складності для відповідних методів.

Знизу ви повинні вибрати реалізацію, яка добре адаптується до ваших типових випадків використання. Очікуваний час доступу в можливий, якщо не завжди гарантується. Залежно від використовуваного методу, важливим є утримання низького рівня; вам потрібно розмістити (очікуваний) час доступу порівняно з простором накладних витрат. Очевидно, хороший вибір для також є центральним.O(1)αh


1] Оскільки довільно тупі неінформовані програмісти можуть надати , будь-яке припущення щодо його якості є практичним розтягненням. 2] Зауважте, як це збігається з рекомендаціями щодо використання Java .h
Hashtable


10

Досконала хеш - функція може бути визначена як ін'єкційних функція з безлічі на підмножина цілих чисел . Якщо для ваших потреб і зберігання даних існує ідеальна хеш-функція, ви можете легко отримати поведінку . Наприклад, ви можете отримати продуктивність з хеш - таблиці для наступної задачі: дані масив цілих чисел і безліч цілих чисел, визначити , є чи містить для кожного . Етап попередньої обробки передбачає складання хеш-таблиці в подальшим перевіркою кожного елемента проти нього вS{0,1,2,...,n}O(1)O(1)lSlxxSO(|l|)SO(|S|) . Загалом це . Наївна реалізація за допомогою лінійного пошуку може бути ; використовуючи двійковий пошук, ви можете робити (зауважте, що це рішення - простір , оскільки хеш-таблиця повинна відображати окремі цілі числа в для різних бін).O(|l|+|S|)O(|l||S|)O(log(|l|)|S|)O(|l|)l

EDIT: Щоб уточнити, як генерується хеш-таблиця в :O(|l|)

Список містить цілі числа від кінцевого безлічі , можливо , з повторами і . Хочемо визначити, чи - . Для цього попередньо обчислюємо хеш-таблицю для елементів : таблиця пошуку. Хеш-таблиця буде кодувати функцію . Для того, щоб визначити , спочатку припустимо для всіх . Потім лінійно просканувати елементів з , вважаючи . Це займає час іlUNSUxSllh:U{true,false}hh(x)=falsexUylh(y)=trueO(|l|)O(|U|) простір.

Зауважте, що мій оригінальний аналіз припускав, що містить принаймні різних елементів. Якщо вона містить менше різних чітких елементів (скажімо, ), потреба в просторі може бути вищою (хоча вона не більше ).lO(|U|)O(|1|)O(|U|)

EDIT2: Хеш-таблицю можна зберігати як простий масив. Хеш - функція може бути тотожною функції на . Зауважте, що функція ідентичності є тривіально ідеальною хеш-функцією. - хеш-таблиця і кодує окрему функцію. Мене неодноразово / плутають деякі з перерахованих вище, але я спробую це вдосконалити найближчим часом.Uh


Чи можете ви розгорнути частину, де ви складаєте хеш-таблицю в ? Я бачу, як це зробити, якщо ви не турбуєтесь про зіткнення, але це означає, що пізніші пошуки можуть зайняти більше , аж до . O(|l|)O(|S|)O(|l||S|)
Жиль

Я не розумію визначення . Ви визначаєте функцію, але не пояснюєте, як вона представлена; Ви могли б написати кілька рядків псевдокоду? Існує також проблема позначення; та bijective не йдуть добре разом. hh:U{false,true}h
Жиль

@Gilles Це в основному просто використовується як таблиця пошуку для членства в списку. Якщо у вас є ідеальна хеш-функція з відомим та дешевим зворотним, замість того, щоб зберігати саму річ, вам потрібно зберігати лише 1 біт (чи додана річ з унікальним хешем). Якщо можливі зіткнення, я думаю, що це стосується фільтра Блюма, але у будь-якому випадку можна дати певне "ні" питанню про членство, що все ще корисно у багатьох сценаріях.
Patrick87

9

Ідеальна хеш-функція призведе до найгіршого пошуку .O(1)

Більше того, якщо максимальна кількість можливих зіткнень дорівнює , то в найгіршому випадку пошук хеш-таблиці може бути . Якщо очікувана кількість зіткнень дорівнює , то в середньому випадку пошук пошуку хеш-таблиці може бути .O ( 1 ) O ( 1 ) O ( 1 )O(1)O(1)O(1)O(1)


Ідеальна хеш-функція була б ідеальною, але як її отримати? Скільки це буде коштувати мені? І як я можу знати, яка максимальна чи очікувана кількість зіткнень?
Жиль

2
@Gilles досконала хеш-функція - це будь-яка функція, яка створить унікальний хеш для всіх можливих входів. Якщо ваші можливі введення обмежені (і унікальні), це зробити нескладно.
Rafe Kettler

1
@RafeKettler Мої дані, як правило, є рядками або складовими структурами даних, і я зазвичай додаю та видаляю записи в міру розвитку моїх даних. Як зробити для цього ідеальний хеш?
Жил

4
Так, але в цьому справа. Детермінованої ідеальної хеш-функції не існує, якщо домен більше діапазону.
Суреш

@Suresh: Якщо вам дозволено вибрати нову хеш-функцію та збільшити розмір таблиці, коли виникає зіткнення, ви завжди можете знайти (детерміновану) хеш-функцію, що - для даних, які вже є в таблиці плюс одна нова елемент, який ви намагаєтеся вставити - не має зіткнень (є "ідеальним"). Ось чому динамічне ідеальне хешуваннявання періодично вибирає нову випадкову хеш-функцію.
Девід Кері
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.