Экономия на инициализации массива

19

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

Например, почему это может быть удивительно:

Скажем, вы пытаетесь смоделировать в худшем случае хеш-таблицу (для каждого из вставки / удаления / поиска) целых чисел в диапазоне [ 1 , n 2 ] .O(1)[1,n2]

Вы можете выделить массив размером бита и использовать отдельные биты для представления существования целого числа в хеш-таблице. Примечание: выделение памяти считается O ( 1 ) времени.n2O(1)

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

Таким образом , в сущности, у вас есть «идеальный» реализацию хеш - функции, которая для последовательности операций использует thetas ; ( п 2 ) пространство, но работает в O ( N ) времени!nΘ(n2)O(n)

Обычно можно ожидать, что ваше время выполнения будет как минимум таким же плохим, как и использование вами пространства!

Примечание: приведенный выше пример может быть использован для реализации разреженного набора или разреженной матрицы, так что, я полагаю, он представляет не только теоретический интерес.

Итак, вопрос:

Как можно иметь массив, подобный структуре данных, который позволяет нам пропустить этап инициализации?

Арьябхата
источник
@Aryabhata Какую ссылку вы упомянули?
Uli
1
«использование памяти» - это не то же самое, что «выделение, но никогда не обращение к памяти», поэтому я думаю, что мотивирующий «парадокс» не совсем существует.
Рафаэль
1
Я думаю, что первый абзац довольно ясен: имейте значение по умолчанию, фактически не тратя время на заполнение массива значением по умолчанию. Ответ, в случае, если у кого-то есть время, чтобы написать это раньше, чем я, здесь: scholar.google.co.uk/… В моем блоге также есть очень краткое объяснение rgrig.blogspot.co.uk/2008/12/array -puzzle-solution.html
rgrig
@uli: Это очень важный вопрос, я давно его прочитал .
Арьябхата
@ Рафаэль: Это все еще удивительно, когда вы слышите о такой вещи в первый раз. Большинство парадоксов не такие :-)
Арьябхата

Ответы:

15

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

APVnpos

init:
  pos <- 0

set(i,x):
if not(V[i] < pos and P[V[i]] = i) 
  V[i] <- pos, P[pos] <- i, pos <- pos + 1
A[i] <- x

get(i):
if (V[i] < pos and P[V[i]] = i) 
  return A[i] 
else 
  return empty 

AsetVPA

P0pos1AiAPiV[i]P[V[i]]iA[i]PA[i]V[i]P0..pos1P[j]AP[j]iA[i]

O(n)O(1)posO(n)

zotachidil
источник
P[V[i]]iA[i]
Это так, но тогда pos будет меньше, чем V [i], не так ли? Потому что иначе это было бы не случайно. Поскольку, имея pos выше, чем V [i], это означает, что мы специально установили значение P для индекса V [i] на определенное значение, которое мы выбрали, а именно i.
wolfdawn
Обратите внимание, что это классический пример того, что невозможно сделать в (переносном) C.
TLW