Дизайн Hashtable - PullRequest
       1

Дизайн Hashtable

19 голосов
/ 23 марта 2011

Мне задали этот вопрос в интервью, и меня оставили в тупике, хотя я и нашел ответ, но мне было неудобно мое решение.Я хотел посмотреть, как эксперты относятся к этому вопросу.

Я точно цитирую вопрос, который возник из интервьюера.«Разработайте хеш-таблицу. Вы можете использовать любую структуру данных, какую захотите. Я хотел бы посмотреть, как вы реализуете время поиска O (1)».Наконец он сказал, что это больше похоже на имитацию хэш-таблицы с помощью другой структуры данных.

Может кто-нибудь подсказать мне больше информации по этому вопросу.Спасибо!

PS: Основная причина, по которой я задаю этот вопрос, состоит в том, чтобы узнать, как опытный дизайнер начнет с дизайна для этой проблемы && еще одна вещь, которую я как-то прояснил на основе других заданных вопросовно этот вопрос был в моей голове, и я хотел найти ответ!

Ответы [ 6 ]

35 голосов
/ 23 марта 2011

Это довольно стандартный вопрос для собеседования, который показывает, что вы понимаете основные понятия, являющиеся полезными структурами данных Java, например HashSet s и HashMap s.

Вы бы использовали массив списков, которые обычно называются buckets . Вы начинаете свою хеш-таблицу с заданной емкостью n , то есть у вас есть массив из 10 списков (все пустые).

Чтобы добавить объект в свою таблицу, вы вызываете функцию hashCode objects, которая дает вам int (число в довольно большом диапазоне). Поэтому вам нужно по модулю hashCode относительно n дать вам корзину, в которой он живет. Добавьте объект в конец списка в этой корзине.

Чтобы найти объект, вы снова используете hashCode и функцию mod, чтобы найти корзину, а затем должны пройтись по списку, используя .equals(), чтобы найти правильный объект.

По мере заполнения таблицы вы будете выполнять все более и более линейный поиск, поэтому вам, в конечном счете, придется повторно хэшировать. Это означает создание совершенно новой, более крупной таблицы и помещение объектов в нее снова.

Вместо использования List в каждой позиции массива вы можете пересчитать другую позицию сегмента, если та, которую вы хотите заполнить, распространенным методом является квадратичное зондирование . Это имеет то преимущество, что не требует каких-либо динамических структур данных, таких как списки, но является более сложным.

2 голосов
/ 23 марта 2011

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

У вас есть постоянный поиск местоположения массива и линейный поиск значений хеша внебольшой список там.

1 голос
/ 25 марта 2011

Если бы я был на вашем месте, я бы сделал следующее:

  • Обсудите, что такое хеш-таблица и в каких ситуациях ее следует использовать.
  • Обсудитеодна из реализаций (например, реализация .net Framework) с точки зрения потребителя.
  • Обсудите «Как HashTable работает внутри» с интервьюером.Это очень важно.Вы сможете разработать его, только если знаете, как работает хеш-таблица.
  • Устраните проблему: a. Выбор структуры данных b. Выбор функции хеширования
  • Использование TDD (разработка через тестирование)) разработать и реализовать класс HashTable.Используйте только ту функциональность, о которой вы просили.
0 голосов
/ 29 августа 2013

Хеш-таблица позволяет эффективно вставлять и извлекать данные (обычно в постоянном / O (1)) времени.Для этого мы используем очень большой массив для хранения целевых значений и хеш-функцию, которая обычно отображает целевые значения в хеш-значения, которые являются ничем иным, как действительными индексами в этом большом массиве.Хеш-функция, которая идеально хэширует значения, которые должны быть сохранены в уникальном ключе (или индексе в таблице), называется идеальной хеш-функцией.Но на практике для хранения таких значений, для которых нет известного способа получения уникальных хеш-значений (индексов в таблице), мы обычно используем хеш-функцию, которая может сопоставить каждое значение с конкретным индексом, чтобы коллизия могла быть минимальной.Здесь столкновение означает, что два или более элементов, которые должны быть сохранены в хеш-таблице, соответствуют одному и тому же хеш-значению.

Теперь перейдем к исходным вопросам, а именно: «Разработайте хеш-таблицу. Вы можете использовать любую структуру данных, какую пожелаете. Я хотел бы посмотреть, как вы реализуете время поиска O (1)».».В заключение он сказал, что это больше похоже на моделирование хеш-таблицы с помощью другой структуры данных. "

Просмотр возможен ровно за O (1) раз, в случае, если мы можем разработать идеальную хеш-функцию.структура все еще является массивом. Но это зависит от значений, которые будут сохранены, можем ли мы разработать идеальную хеш-функцию или нет. Например, рассмотрим строки в английском алфавите. Так как не существует известной хеш-функции, которая могла бы сопоставить каждое действительное английское слово суникальное значение типа int (32 бита) (или long long int 64 бита), поэтому всегда будут возникать коллизии. Чтобы справиться с коллизиями, мы можем использовать отдельный метод цепочки обработки коллизий, в котором каждый слот хеш-таблицы хранит указатель на связанныйсписок, который фактически хранит все хеширование элемента в этом конкретном слоте или индексе. Например, рассмотрим хеш-функцию, которая рассматривает каждую строку английского алфавита как число на основе 26 (потому что в английском алфавите 26 символов), это можно закодировать как:

unsigned int hash(const std::string& word)
{
    std::transform(word.begin(), word.end(), word.begin(), ::tolower);
    unsigned int key=0;
    for(int i=0;i<word.length();++i)
    {
         key = (key<<4) + (key<<3)+(key<<2) + word[i];
         key = key% tableSize;
    }
    return key;
}

Где tableSizeэто правильно выбранное простое число, которое больше, чем общее количество слов английского языка, предназначенных для сохранения в хеш-таблице.

Ниже приведены результаты со словарем размера 144554 и таблицей размера = 144563:

[Элементы, отображаемые в одну ячейку -> Количество таких слотов в хеш-таблице] =======>

[ 0  -->   53278 ]
[1 --> 52962 ]
[2 --> 26833 ]
[3 --> 8653  ]
[4 --> 2313 ]
[5 --> 437 ]
[6  --> 78 ]
[7  -->  9 ]

В этом случае для поиска элементов, которые были отображеныдля ячеек, содержащих только один элемент, поиск будет O (1), но в случае, если он сопоставляется с ячейкой, которая содержит более 1 элементов, мы должны выполнить итерацию по этому связанному списку, который может содержать от 2 до 7 узлов, а затемсможет узнать этот элемент.Так что это не постоянно в этом случае.

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

0 голосов
/ 11 августа 2013

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

Набор S имеет разумные размеры S⊆ U. Итак, этот набор S имеет разумные размеры, как и у вас номер телефона ваших друзей.

Выбор структуры данных для реализации Без структуры данных мы не получим хорошего решения. Мы могли бы использовать массив для быстрой вставки, удаления и поиска, но он займет много места, так как размер юниверса очень велик. Кроме того, имя вашего друга должно быть целым числом, а пространство должно быть пропорционально вселенной.

С другой стороны, мы могли бы использовать связанный список. Это заняло бы столько же места, сколько существует объектов, т. Е. Set S, но 3 операции не были бы O (1). Чтобы решить эту проблему, мы можем использовать оба.

Таким образом, решение состоит в том, чтобы использовать лучшее из обоих миров, то есть быстрый поиск массивов и небольшое хранилище размера, как список ссылок.

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

Вставка Алисы:
int k = hashFunc(alice);<br/> arr[k] = Alice //this takes O(1) time<br/>

Поиск для Алисы:
int k = hashFunc(alice);<br/> string name = arr[k] ;<br/> print name;//prints alice <br/>
Конечно, это не так просто, но это то, что я могу объяснить прямо сейчас. Пожалуйста, дайте мне знать, где мне не ясно. Спасибо. Для получения дополнительной информации о хэш-таблице см. здесь

0 голосов
/ 23 марта 2011

Использовать массив => O (1)

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...