#java #algorithm #data-structures #hashtable
#java #алгоритм #структуры данных #хеш-таблица
Вопрос:
Итак, вот актуальный вопрос (это для домашнего задания):
Хеш-таблица — это структура данных, которая позволяет получать доступ и манипулировать датой в постоянное время (O (1)). Массив хэш-таблицы должен быть инициализирован в null во время создания хэш-таблицы, чтобы идентифицировать пустые ячейки. В большинстве случаев временные затраты огромны, особенно учитывая, что большинство ячеек никогда не будут прочитаны. Мы просим вас реализовать хэш-таблицу, которая позволяет обойти эту проблему ценой более тяжелой вставки, но при этом с постоянным временем. Для целей этого домашнего задания и для упрощения вашей работы мы предполагаем, что вы не можете удалять элементы в этой хеш-таблице.
В архиве этого домашнего задания вы найдете интерфейс хэш-таблицы, которую вам нужно заполнить. Вы можете использовать функцию hashcode() из java в качестве хеш-функции. Вам придется использовать векторную структуру данных из Java, чтобы обойти инициализацию, и вы должны сами найти, как это сделать. Вы можете вставлять элементы только в конце вектора, чтобы сложность по-прежнему была O (1) .
Вот несколько фактов, которые следует учитывать:
-
В хеш-таблице, содержащей целые числа, таблица содержит числовые значения (но они не имеют никакого смысла).
-
В стеке вы не можете получить доступ к элементам поверх самого высокого элемента, но вы точно знаете, что все значения действительны. Кроме того, вы знаете индекс самого высокого элемента.
Используйте эти факты, чтобы обойти инициализацию хеш-таблицы. Таблица должна использовать линейное зондирование для разрешения коллизий.
Кроме того, вот интерфейс, который мне нужно реализовать для этого домашнего задания:
public interface NoInitHashTable<E>
{
public void insert(E e);
public boolean contains(E e);
public void rehash();
public int nextPrime(int n);
public boolean isPrime(int n);
}
Я уже реализовал nextPrime и isPrime (я не думаю, что они отличаются от обычной хеш-таблицы). Три других, которые мне нужно выяснить.
Я много думал об этом и обсуждал это со своим товарищем по команде, но я действительно ничего не могу найти. Мне нужно только знать основной принцип его реализации, я могу справиться с кодированием.
tl; dr Мне нужно реализовать хэш-таблицу массива, которая работает без инициализации массива в null в начале. Вставка должна выполняться в постоянное время. Мне нужно только знать основной принцип того, как это сделать.
Комментарии:
1. Интересная задача. Я предполагаю, что профессор дал вам еще несколько советов во время недавних лекций — вам следует вспомнить, что он сказал на последних двух занятиях, чтобы посмотреть, есть ли какие-то дополнительные подсказки.
2. Подсказка: нигде он не определяет интерфейс для установки размера хэш-таблицы.
3. Чтобы получить временную сложность O (1), вам нужен идеальный алгоритм хеширования. т. Е. Никаких столкновений. Это редко бывает в реальных приложениях. 😉
4. @PeterLawrey, O(1) не означает отсутствия столкновений. Если количество столкновений ограничено, у вас все равно может быть O (1) . И обычные реализации хеш-таблиц — O (1), предполагая, что у вас есть разумное распределение хеш-кодов.
Ответ №1:
Я думаю, что видел это в книге как упражнение с ответом в конце, но я не могу вспомнить, в какой книге или где. Как правило, это относится к вопросу о том, почему мы обычно концентрируемся на времени, которое занимает программа, а не на пространстве — программе, которая работает эффективно во времени, не должно требоваться огромное количество места.
Вот некоторый псевдокод, который проверяет, является ли ячейка в хэш-таблице допустимой. Я оставлю работу по изменению структур данных, которые он определяет, чтобы сделать другую ячейку в хеш-таблице действительной в качестве оставшегося упражнения для читателя.
// each cell here is for a cell at the same offset in the
// hash table
int numValidWhenFirstSetValid[SIZE];
int numValidSoFar = 0; // initialise only this
// Only cells 0..numValidSoFar-1 here are valid.
int validOffsetsInOrderSeen[SIZE];
boolean isValid(int offsetInArray)
{
int supposedWhenFirstValid =
numValidWhenFirstSetValid[offsetInArray]
if supposedWhenFirstValid >= numValidSoFar)
{
return false;
}
if supposedWhenFirstValid < 0)
{
return false;
}
if (validOffsetsInOrderSeen[supposedWhenFirstValid] !=
offsetInArray)
{
return false;
}
return true;
}
Редактировать — это упражнение 24 в разделе 2.2.6 Knuth Vol. 1. Предоставленный ответ ссылается на упражнение 2.12 «Проектирование и анализ компьютерных программ» Ахо, Хопкрафта и Ульмана. Вы можете избежать любых обвинений в плейгаризме в своем ответе, сославшись на источник заданного вам вопроса 🙂
Комментарии:
1. Я не брал это из этой книги: это был вопрос, заданный для домашнего задания, и он ни на что не ссылался.
2. Спасибо за пример. Я не совсем понимаю, что представляет переменная. Что такое numValidWhenFirstSetValid и suppowedWhenFirstValid ? Спасибо
3. Предположим, что вы заполняете хэш-слоты 3, 5, 2 в таком порядке, поэтому validOffsetsInOrderSeen[] = {3, 5, 2}, numValidWhenFirstSetValid[3] = 0, numValidWhenFirstSetValid[5] = 1, numValidWhenFirstSetValid[2] = 2. numValidWhenFirstSetValid[k] — количество допустимых слотоввидно до сих пор, когда заполнен слот k. Вы знаете, что validOffsetsInOrderSeen[0..numValidSoFar] перечисляет заполненные слоты, поэтому, чтобы проверить, что слот k был заполнен, вы устанавливаете supposedWhenFirstValid = numValidWhenFirstSetValid[k] . Если слот k пуст, это может выглядеть правдоподобно, поэтому вы проверяете validOffsetsInOrderSeen[предположениеwhenfirstvalid] == k .
Ответ №2:
Пометьте каждый элемент в хэш-таблице некоторым цветом (1, 2, …)
Например, текущий цвет:
int curColor = 0;
Когда вы помещаете элемент в хэш-таблицу, свяжите с ним текущий color ( curColor
)
Если вам нужно выполнить поиск, отфильтруйте элементы, которые не имеют одинакового цвета ( element.color == curColor
)
Если вам нужно очистить хэш-таблицу, просто увеличьте текущий color ( curColor
)
Комментарии:
1. Разве это не затруднит поиск O (1)?
2. Среднее время поиска для хеш-таблицы равно o (n). Но когда количество элементов становится больше размера хеш-таблицы, время поиска будет увеличено. Вы можете очистить всю хеш-таблицу, если количество элементов (старых и текущих) слишком велико
3. Извините, я имел в виду O (n) . Я думаю, что ваше решение сделало бы O (n) . Но требование состоит в том, чтобы сделать его O(1) . Хэш-таблицам обычно удается этого добиться.
4. @svick, Упс, я допустил ошибку в своем комментарии.. Время поиска равно O (1), потому что существует простая хеш-таблица со средним временем поиска O (1)