Risparmio sull'inizializzazione dell'array


19

Di recente ho letto che è possibile disporre di array che non devono essere inizializzati, ovvero è possibile utilizzarli senza dover perdere tempo a cercare di impostare ciascun membro sul valore predefinito. cioè è possibile iniziare a usare l'array come se fosse stato inizializzato dal valore predefinito senza inizializzarlo. (Mi dispiace, non ricordo dove ho letto questo).

Ad esempio, perché questo può essere sorprendente:

Supponiamo che tu stia cercando di modellare il caso peggiore hashtable (per ciascuno di insert / delete / search) di numeri interi nell'intervallo .O(1)[1,n2]

È possibile allocare un array di dimensioni bit e utilizzare singoli bit per rappresentare l'esistenza di un numero intero nella tabella hash. Nota: l'allocazione della memoria è considerata il tempo .n2O(1)

Ora, se non è necessario inizializzare affatto questo array, qualsiasi sequenza di operazioni su questa hashtable è ora il caso peggiore .nO(n)

Quindi, in effetti, hai un'implementazione hash "perfetta", che per una sequenza di operazioni utilizza lo spazio , ma viene eseguita in time!nΘ(n2)O(n)

Normalmente ci si aspetterebbe che il tempo di esecuzione sia almeno pari a quello dell'uso dello spazio!

Nota: l'esempio sopra potrebbe essere usato per un'implementazione di un set sparse o di una matrice sparse, quindi suppongo non sia solo di interesse teorico.

Quindi la domanda è:

Come è possibile avere una matrice come la struttura dei dati che ci consente di saltare il passaggio di inizializzazione?


@Aryabhata Qual è il riferimento che hai citato?
uli

1
"usare la memoria" non è lo stesso di "aver allocato ma non aver mai avuto accesso alla memoria", quindi penso che il "paradosso" motivante non sia del tutto esistente.
Raffaello

1
Penso che il primo paragrafo sia abbastanza chiaro: avere un valore predefinito, senza effettivamente impiegare tempo a riempire l'array con il valore predefinito. La risposta, nel caso in cui qualcun altro abbia il tempo di scriverlo prima di me, è qui scholar.google.co.uk/… C'è anche una breve spiegazione sul mio blog rgrig.blogspot.co.uk/2008/12/12/array -puzzle-solution.html
rgrig

@uli: questa è una domanda di base, in realtà l'ho letta molto tempo fa.
Aryabhata,

@Raphael: È ancora sorprendente quando si sente parlare di una cosa del genere la prima volta. La maggior parte dei paradossi non sono :-)
Aryabhata,

Risposte:


15

Questo è un trucco molto generale, che può essere utilizzato per scopi diversi dall'hashing. Di seguito do un'implementazione (in pseudo-codice).

Lasciare tre vettori non inizializzati , P e V di dimensione n ciascuno. Li useremo per eseguire le operazioni richieste dalla nostra struttura di dati. Manteniamo anche una variabile p o s . Le operazioni sono implementate come segue: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 

La matrice semplicemente memorizza i valori passati attraverso il s e t procedura. Le matrici V e P funzionano come certificati che possono dire se una determinata posizione in A è stata inizializzata.AsetVPA

Si noti che in ogni momento gli elementi in che vanno da 0 a p o s - 1 vengono inizializzati. Possiamo quindi tranquillamente usare questi valori come un certificato per i valori inizializzati in A . Per ogni posizione i in A inizializzata, c'è un elemento corrispondente nel vettore P il cui valore è uguale a i . Questo è indicato da V [ i ] . Pertanto, se osserviamo l'elemento corrispondente, P [ V [ i ] ] e il suo valore è iP0pos1AiAPiV[i]P[V[i]]i, sappiamo che è stato inizializzato (poiché P non mente mai, perché tutti gli elementi che stiamo prendendo in considerazione sono inizializzati). Allo stesso modo, se A [ i ] non è inizializzato, allora V [ i ] può puntare a una posizione in P al di fuori dell'intervallo 0 .. p o s - 1 , quando sappiamo per certo che non è inizializzato, o può puntare a una posizione all'interno di tale intervallo. Ma questo particolare P [ j ] corrisponde a una posizione diversa in A , e quindiA[i]PA[i]V[i]P0..pos1P[j]A , quindi sappiamo che A [ i ] non è stato inizializzato.P[j]iA[i]

È facile vedere che tutte queste operazioni vengono eseguite in tempo costante. Inoltre, lo spazio utilizzato è per ciascuno dei vettori e O ( 1 ) per la variabile p o s , quindi O ( n ) in totale.O(n)O(1)posO(n)


Ma non è possibile che per caso uguale a i senza che A [ i ] sia mai stato impostato? P[V[i]]iA[i]
Robert S. Barnes,

Lo è ma allora pos sarà più piccolo di V [i] ora no? Perché altrimenti non sarebbe per caso. Poiché avendo pos maggiore di V [i], significa che abbiamo impostato specificamente il valore di P all'indice V [i] su un valore specifico che abbiamo scelto, vale a dire i.
Wolfdawn,

Si noti che questo è un classico esempio di qualcosa che è impossibile fare in (portatile) C.
TLW
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.