Quale struttura di dati memorizzerebbe in modo efficiente intervalli di numeri interi?


10

Devo mantenere una raccolta su numeri interi compresi tra 0 e 65535 in modo da poter eseguire rapidamente le seguenti operazioni:

  • Inserisci un nuovo numero intero
  • Inserisci un intervallo di numeri interi contigui
  • Rimuovi un numero intero
  • Rimuovi tutti i numeri interi sotto un numero intero
  • Verifica se è presente un numero intero

I miei dati hanno la proprietà che spesso contiene esecuzioni di numeri interi nella raccolta. Ad esempio, la raccolta potrebbe essere in un determinato momento:

{ 121, 122, 123, 124, 3201, 3202, 5897, 8912, 8913, 8914, 18823, 18824, 40891 }

L'approccio più semplice è solo quello di usare un albero binario bilanciato come il C ++ std :: set, tuttavia, usando quello, non sto sfruttando il fatto che ho spesso serie di numeri. Forse sarebbe meglio conservare una collezione di gamme? Ciò significa che un intervallo deve essere in grado di essere suddiviso se viene rimosso un numero intero al suo centro o unito se lo spazio tra due intervalli viene riempito.

Esistono strutture dati esistenti che potrebbero essere adatte a questo problema?

Risposte:


9

Ti suggerisco di utilizzare un albero di ricerca binario, aumentato in modo che le foglie possano contenere un intervallo (una serie di numeri interi consecutivi). Mantenere l'invariante che gli intervalli non si sovrappongano e siano in ordine (seguendo l'invariante dell'albero di ricerca). (Questo può essere considerato un caso speciale di un albero intervallo o di un segmento, per il caso speciale in cui gli intervalli non si sovrappongono.)

Questa struttura di dati è in grado di supportare tutte le operazioni in tempo, dove è il numero di intervalli. Dato che siamo garantiti , mi aspetto che questo sia abbastanza efficiente. (In particolare, sì, puoi dividere un intervallo in due pezzi o unire due intervalli adiacenti in un singolo intervallo nel tempo .)n n 65535 O ( lg n )O(lgn)nn65535O(lgn)


5

Prima di tutto, la tua domanda è formulata in modo molto scadente, se non altro perché "rapidamente" non significa molto. Dovrai fornire alcune metriche sul significato di "rapido".

Oltre a ciò, quando si cerca di elaborare un progetto per un problema, è necessario prima capire molto bene il problema e porre molte altre domande. Le domande rilevanti in questo caso sembrano essere (in nessun ordine particolare):

  • Tutte queste operazioni devono essere ugualmente veloci o alcune sono più importanti di altre?
  • Ci sono altre considerazioni?
  • La memoria è una preoccupazione?
  • La capacità di eseguire inserimenti, rimozioni e ricerche da più thread è una preoccupazione?
  • Il carico di lavoro si concentra principalmente sull'inserimento? Rimozione? Guardando in alto?

In secondo luogo, se il tuo dominio problematico è davvero questa discussione sembra sciocca. È davvero necessario un algoritmo intelligente e sofisticato ? Soprattutto quando un array semplice è un'opzione eccellente, che copre le singole operazioni di numero intero in tempo costante, le operazioni di intervallo in tempo lineare e costa spazio lineare?[0,65535]

Per un po 'più di lavoro, potresti risparmiare spazio se questo è un problema, a scapito della velocità memorizzando i dati come bit in 8192 numeri interi. Sebbene concettualmente le operazioni a singolo numero intero sarebbero comunque a tempo costante e le operazioni a distanza a valori interi sarebbero comunque a tempo lineare, sarebbero più lente.

Quindi, se questo è davvero il tuo problema, direi di usare un array e passare ad altre cose più importanti con il codice.

Se questo non è davvero il tuo problema e ci sono altre considerazioni che non hai inoltrato (ad es. Forse il dominio non è proprio e stavi cercando di semplificare il problema di cui ti stavi chiedendo) allora avrai bisogno per porre di nuovo la tua domanda, questa volta raccontandoci il problema reale .[0,65535]


3

Potresti considerare una struttura di dati Integer come un albero di Van Emde Boas . Una struttura di dati integer funziona su un universo fisso . Alcune delle operazioni che hai citato possono essere implementate in modo molto efficiente. In particolare, l'inserimento, l'eliminazione e la richiesta di un singolo elemento vengono eseguiti in . Le altre operazioni (inserimento / eliminazione in blocco) potrebbero essere più costose, tuttavia, usando i bittrick sull'albero di Van Emde Boas dovresti essere in grado di accelerare di un fattore circa la dimensione della parola del tuo sistema.O ( registro registro u )U={0,,u1}O(loglogu)

A seconda della struttura dei dati potrebbero esserci molte alternative intelligenti su come archiviare i dati.

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.