Создайте Hashtable

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

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

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

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

Ответы

Ответ 1

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

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

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

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

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

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

Ответ 2

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

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

Ответ 3

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

  • Обсудите, что такое хэш-таблица и в каких ситуациях она должна использоваться.
  • Обсудите одну из реализаций (например, реализацию .NET Framework) с точки зрения потребителя.
  • Обсудите "Как HashTable функционирует внутренне" с интервьюером. Это очень важно. Вы сможете проектировать его только в том случае, если вы знаете, как работает хэш-таблица.
  • Прервать проблему: a. Выбор структуры данных. b. Выбор функции хеширования.
  • Используйте TDD (Test Driven Development) для разработки и реализации класса HashTable. Используйте только те функции, о которых вы просили.

Ответ 4

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

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

Ответ 5

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

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

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

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

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

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

Вставка alice:
int k = hashFunc(alice);
arr[k] = Alice //this takes O(1) time

Поиск для Алисы:
int k = hashFunc(alice);
string name = arr[k] ;
print name;//prints alice

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

Ответ 6

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

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

Взгляд вверх возможен в точно время O (1), если мы можем создать идеальную хэш-функцию. Основная структура данных по-прежнему является массивом. Но это зависит от сохраненных значений, можем ли мы создать идеальную хеш-функцию или нет. Например, рассмотрим строки английского алфавита. Поскольку нет хеш-функции, которая может сопоставить каждое действующее английское слово с уникальным значением int (32 бит) (или long long int 64 bit), поэтому всегда будут возникать конфликты. Чтобы справиться с столкновением, мы можем использовать отдельный метод цепочки обработки столкновений, в котором каждый слот хэш-таблицы хранит указатель на связанный список, который фактически хранит все хеширование элементов в этом конкретном слоте или индексе. Например, рассмотрим хеш-функцию, которая рассматривает каждую английскую строку алфавита как число на основе 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), а очень близко к нему.