Збереження при ініціалізації масиву


19

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

Наприклад, чому це може дивувати:

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

Ви можете виділити масив розміром біт і використовувати окремі біти для представлення існування цілого числа в хештелі. Примітка: розглядається розподіл пам'ятіn2 часом.O(1)

Тепер, якщо вам взагалі не довелося ініціалізувати цей масив, будь-яка послідовність скажувань операцій на цьому хештелі тепер є гіршим випадком On .O(n)

Отже, по суті, у вас є "ідеальна" хеш-реалізація, яка для послідовності операцій використовує Θ ( n 2 ) простір, але працює в O ( n ) час!nΘ(n2)O(n)

Зазвичай можна очікувати, що час роботи буде принаймні таким же поганим, як використання вашого простору!

Примітка. Приклад, наведений вище, може бути використаний для реалізації розрідженого набору або розрідженої матриці, тому, мабуть, це не лише теоретичний інтерес.

Отже, питання:

Як можливо мати масив типу структури даних, який дозволяє нам пропустити етап ініціалізації?


@Aryabhata Про яку згадку ви згадували?
uli

1
"використання пам'яті" - це не те саме, що "виділити, але ніколи не отримати доступ до пам'яті", тому я вважаю, що мотиваційний "парадокс" не зовсім існує.
Рафаель

1
Я думаю, що перший абзац досить зрозумілий: мати значення за замовчуванням, фактично не потребуючи часу для заповнення масиву зі значенням за замовчуванням. Відповідь, якщо хтось ще встигне написати це до того, як я це зробити, є тут scilar.google.co.uk/… Є також дуже коротке пояснення в моєму блозі rgrig.blogspot.co.uk/2008/12/array -puzzle-solution.html
rgrig

@uli: Це насіннєве питання, я насправді читав це давно назад.
Ар'ябхата

@Raphael: Досі дивно, коли ти чуєш про таке щось вперше. Більшість парадоксів - це не :-)
Ар'ябхата

Відповіді:


15

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

Нехай три неініціалізовані вектори , P і V розміром n кожен. Ми будемо використовувати їх для виконання операцій, які вимагає наша структура даних. Ми також підтримуємо змінну p o s . Операції реалізуються наступним чином:АПVнpос

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 

Масив просто зберігає значення, передані через процедуру s e t . Масиви V і P працюють як сертифікати, які можуть визначити, чи була ініціалізована дана позиція в A.АсетVPA

Зауважимо, що кожного моменту елементи діапазоні від 0 до p o s - 1 ініціалізуються. Тому ми можемо сміливо використовувати ці значення в якості сертифіката для ініціалізованих значень в A . Для кожного положення i в A, яке ініціалізується, у векторі P є відповідний елемент , значення якого дорівнює i . На це вказує V [ i ] . Тому, якщо ми подивимось на відповідний елемент, P [ V [ i ] ] і його значення - iP0pos1AiAPiV[i]P[V[i]]iми знаємо, що було ініціалізовано (оскільки P ніколи не бреше, тому що всі елементи, які ми розглядаємо, ініціалізовані). Аналогічно, якщо A [ i ] не ініціалізовано, то V [ i ] може вказувати або на позицію в P поза діапазону 0 .. p o s - 1 , коли ми точно знаємо, що вона не ініціалізована, або може вказувати на позиція в межах цього діапазону. Але саме цей P [ j ] відповідає іншому положенню в А , отжеA[i]PA[i]V[i]P0..pos1P[j]A , тому ми знаємо, що A [ i ] не було ініціалізовано.P[j]iA[i]

Неважко помітити, що всі ці операції виконуються в постійний час. Також використовуваний простір становить для кожного з векторів, а O ( 1 ) для змінної p o s , отже, O ( n ) в цілому.O(n)O(1)posO(n)


Але чи не можливо, що випадково дорівнює i, без того, щоб A [ i ] було встановлено? P[V[i]]iA[i]
Роберт С. Барнс

Це, але тоді поз буде меншим, ніж V [i], чи не так? Тому що інакше це не було б випадково. Оскільки, маючи pos вище, ніж V [i], це означає, що ми спеціально встановили значення P в індексі V [i] на певне значення, яке ми обрали, а саме i.
вовчий світанок

Зауважте, що це класичний приклад того, що неможливо зробити у (портативному) C.
TLW
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.