Implementazione di Fenwick Tree non fissi

1

Sto pensando di implementare un albero di Fenwick di dimensioni non fisse. Cioè, un albero di Fenwick che consente query di intervallo interleaving con l'aggiunta / rimozione di elementi.

Tutte le implementazioni e samples Ho visto finora sono gli alberi di Fenwick a dimensione fissa, in cui è noto il numero di elementi prima della preelaborazione delle frequenze. Usano una matrice di dimensioni fisse, quindi non è possibile aggiungere o rimuovere elementi dopo aver eseguito la pre-elaborazione. (Beh, è possibile, ma avrei bisogno di ricostruire la struttura).

Ho pensato di estendere TreeMap o forse AbstractMap , ma come TreeMap è in realtà un albero rosso-nero, non so come implementare la meccanica rosso-nero (in modo che l'albero rimanga bilanciato) senza perdere le somme cumulative dei nodi coinvolti nel processo di ribilanciamento.

Quindi ho pensato che forse avrei dovuto adottare un altro approccio: perché non estendere o adattare un semplice accesso casuale ArrayList e ricalcolare tutte le somme cumulative quando l'array sottostante viene ridimensionato? Questo naturalmente avrebbe un impatto ma, ehi, è esattamente ciò che fa HashMap .

Questo è il motivo per cui ho voluto chiedere prima qui, nel caso qualcuno l'abbia già fatto, e per verificare quale approccio pensi sia il migliore.

    
posta Federico Peralta Schaffner 25.03.2015 - 19:54
fonte

2 risposte

2

Il Fenwick Tree è una struttura di dati efficiente dal punto di vista dello spazio perché rinuncia ai dati originali e invece memorizza solo alcune versioni "codificate".

Come hai notato, tuttavia, questa codifica significa che non puoi aggiungere o rimuovere un elemento (eccetto che alla coda) senza molto churn.

Se le operazioni di aggiunta / rimozione sono abbastanza frequenti rispetto alla ricostruzione dell'intero array sottostante è possibile nel tuo caso; fallo Questo significherà un picco di latenza, ma non dovrebbe influenzare significativamente il throughput.

Se, d'altra parte, questo overhead non è accettabile, allora il Fenwick Tree non è una struttura dati appropriata per il tuo problema. In questo caso, consiglierei un albero di ricerca binario aumentato.

Assumi l'implementazione dell'albero di ricerca binaria che preferisci (Albero rosso-nero, Albero AVL, Albero di diffusione, ...) o anche un albero B se lo desideri e aumenta le informazioni che ogni nodo / elemento porta con sé :

  • il numero di bambini sinistro e destro
  • la somma dei bambini sinistro e destro

Quando aggiungi / rimuovi elementi devi tenere aggiornati numeri e somme sul percorso che porta alla radice. L'aggiunta e la rimozione sono già O (log N), quindi dal momento che aggiornerai i nodi / elementi O (log N) non cambierai la complessità in modo significativo.

Quindi, implementa nuovi metodi per accedere all'indice e recuperare la somma. Si noti che l'indice non è immediatamente accessibile, ma conoscendo il sottoalbero sinistro sono presenti 4 nodi, se si desidera accedere:

  • indice 2, quindi dovresti passare al sottoalbero sinistro
  • indice 5, quindi sei qui
  • indice 7, allora dovresti fare la sottostruttura giusta (e accedere all'indice 2 nell'albero secondario di destra: 7 - sizeof (left sub-tree) - 1)
risposta data 25.11.2015 - 10:55
fonte
0

Questa è la prima volta che ho sentito parlare di questa struttura dati. A quali alberi di dimensioni stai mirando? A meno che non siano solo migliaia, probabilmente non importa molto quale struttura di dati di base si inizia con.

Da Wikipedia, comprendo che l'accesso basato su indice alla struttura è importante. Per questo motivo, vorrei iniziare con un'implementazione basata su ArrayList semplice per iniziare.

Ricorda che il punto di un ADT è che puoi scambiare i dettagli di implementazione mantenendo intatta l'interfaccia.

    
risposta data 27.03.2015 - 08:50
fonte

Leggi altre domande sui tag