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


70

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

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

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

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


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

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

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

1
Також будьте уважні до передчасної оптимізації; для невеликих (декількох тисяч елементів) даних я часто бачив, що врівноважені двійкові дерева перевершують хештелі за рахунок нижчих накладних витрат (порівняння рядків набагато дешевше, ніж хеш-рядки). O(log⁡n)
— 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: Дійсно? Я думав, що вам потрібні -незалежні функції, які я завжди асоціював з необхідними розширювачами. Я стою виправлений. Трохи видалить мій коментар log⁡n
— Луї

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

21

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

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

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

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

Прикування

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

CnS≈1+α2 and CnU≈1+α22.

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

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

h(v),h(v)−1,…,0,m−1,…,h(v)+1
vα→1
CnS≈12(1+11−α) and CnU≈12(1+(11−α)2).
α<0.75

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

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

CnS≈1αln⁡(11−α) and CnU≈11−α.

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

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


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


10

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

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

Список містить цілі числа від кінцевого безлічі , можливо , з повторами і . Хочемо визначити, чи - . Для цього попередньо обчислюємо хеш-таблицю для елементів : таблиця пошуку. Хеш-таблиця буде кодувати функцію . Для того, щоб визначити , спочатку припустимо для всіх . Потім лінійно просканувати елементів з , вважаючи . Це займає час іlU⊂NS⊆Ux∈Sllh:U→{true,false}hh(x)=falsex∈Uylh(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.