Struttura dei dati per una ricerca efficiente, quando inserimenti e rimozioni sono solo unilaterali


8

Ho bisogno di una struttura di dati per memorizzare un numero n di elementi, ognuno dei quali è associato a tempi diversi ti. n varia e sebbene abbia un limite superiore teorico, si tratta di molti ordini di grandezza più grandi di quelli normalmente utilizzati.

Attraverso la mia applicazione posso garantire che:

  • Gli elementi inseriti sono sempre più recenti di tutti gli elementi esistenti, ovvero se un elemento è associato a un tempo tˇ viene inserito, quindi tˇ>tii1,,n. Gli elementi vengono inseriti uno per uno.

  • Vengono rimossi solo gli elementi più vecchi, ovvero se l'elemento j viene rimosso, quindi tj<ti i{1,,n}{j}. Le rimozioni avvengono principalmente una per una, ma non vi è alcun danno diretto se la rimozione di un elemento è ritardata, a condizione che la frazione di elementi spuri immagazzinati rimanga inferiore a 1.

  • Oltre a inserire e rimuovere, l'unica cosa che devo fare è trovare i due elementi vicini per un certo tempo t~ con miniti<t~<maxiti. Con altre parole ho bisogno di trovare i due elementi  e  tali che e ∄ l ∈ \ {1, ..., n \}: t_j <t_l <t_k .jktj<t~<tkl{1,,n}:tj<tl<tk

I miei criteri per la struttura dei dati sono:

  1. Trovare gli elementi sopra descritti dovrebbe essere il più veloce possibile.
  2. L'inserimento e la rimozione dovrebbero essere rapidi.
  3. La struttura dei dati è relativamente semplice da implementare.

Finché non stiamo parlando di un piccolo offset di runtime, ogni criterio ha la priorità su quello successivo.

La mia ricerca finora ha prodotto che la risposta è probabilmente una specie di albero di ricerca auto-bilanciante, ma non sono riuscito a trovare alcuna informazione quale di esse sia la migliore nel caso di inserimento o eliminazione unilaterale, e probabilmente mi costerà un tempo considerevole per scoprire me stesso. Inoltre, ho trovato solo informazioni incomplete su quanto bene gli alberi si auto-organizzano e quanto velocemente (ad esempio, gli alberi AVL si auto-organizzano più rigidamente degli alberi rosso-neri), per non parlare di come questo è influenzato dall'inserimento o dall'eliminazione su un lato.


4
Questo sta solo eseguendo una ricerca binaria simile ad array in una coda.
o11c,

Risposte:


5

Memorizza gli elementi come una sequenza, ordinati aumentando il timestamp. Utilizzare la ricerca binaria per trovare la posizione in cui si verificherebbe se fosse nella matrice; allora puoi facilmente trovare i due elementi vicini. La ricerca dei due elementi vicini può essere eseguita in tempo.t~O(lgn)

Dovrai anche essere in grado di aggiungere alla fine della sequenza ed eliminare dall'inizio. Quindi, in pratica, hai bisogno di una coda.

Esistono costruzioni standard per una coda. Ad esempio, è possibile memorizzarli in un array, con operazioni di inserimento ed eliminazione ammortizzate . Fondamentalmente, hai un array per gli elementi della sequenza e un indice di inizio (per l'inizio della sequenza) e un indice di fine (per la fine della sequenza). Per eliminare dall'inizio, incrementare l'indice iniziale. Per aggiungere alla fine, incrementare l'indice di fine; se questo supera la fine dell'array esistente, allocare un nuovo array di dimensioni doppie e copiarlo nel nuovo array.O(1)

In alternativa: è possibile memorizzare gli elementi in un albero binario bilanciato. Ciò consentirà di ottenere caso peggiore per tutte le operazioni.O(lgn)

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.