Aggiunta di elementi a un array ordinato


31

Quale sarebbe il modo più veloce per farlo (dal punto di vista algoritmico, oltre che pratico)?

Stavo pensando qualcosa secondo le seguenti linee.

Potrei aggiungere alla fine di un array e quindi usare bubblesort in quanto ha un caso migliore (array totalmente ordinato all'inizio) che è vicino a questo e ha un tempo di esecuzione lineare (nel migliore dei casi).

D'altra parte, se so di iniziare con un array ordinato, posso usare una ricerca binaria per scoprire il punto di inserimento per un dato elemento.

La mia idea è che il secondo modo sia quasi ottimale, ma curioso di vedere cosa c'è là fuori.

Come può essere fatto al meglio?


1
Il modo più veloce, se devi farlo spesso, non è quello di usare un array in primo luogo.
reinierpost,

Albero binario autobilanciante intendi?
soandos,

Sì, forse; vedere le risposte ...
reinierpost

Risposte:


25

Contiamo il numero di letture e scritture di elementi array. Per fare il bubble sort, hai bisogno di accessi (la scrittura iniziale alla fine, poi, nel peggiore dei casi, due letture e due scritture di fare n swap). Per eseguire la ricerca binaria, abbiamo bisogno di 2 log n + 2 n + 1 ( 2 log n per la ricerca binaria, quindi, nel caso peggiore, 2 n per spostare gli elementi dell'array a destra, quindi 1 per scrivere l'elemento dell'array in la sua posizione corretta).1+4nn2logn+2n+12logn2n

Quindi entrambi i metodi hanno la stessa complessità per le implementazioni di array, ma il metodo di ricerca binaria richiede meno accessi di array nel lungo periodo ... asintoticamente, la metà. Ci sono altri fattori in gioco, naturalmente.

In realtà, è possibile utilizzare implementazioni migliori e contare solo gli accessi effettivi all'array (non gli accessi all'elemento da inserire). Potresti fare per l'ordinamento a bolle, e registrare n + 2 n + 1 per la ricerca binaria ... quindi se l'accesso al registro / cache è economico e l'accesso all'array è costoso, cerca dalla fine e spostati lungo la strada (più intelligente ordinamento a bolle per l'inserimento) potrebbe essere migliore, anche se non asintoticamente.2n+1logn+2n+1

Una soluzione migliore potrebbe comportare l'utilizzo di una diversa struttura di dati. Le matrici forniscono O (1) accessi (accesso casuale), ma gli inserimenti e le eliminazioni potrebbero costare. Una tabella hash potrebbe avere O (1) inserimenti ed eliminazioni, gli accessi costerebbero. Altre opzioni includono BST e heap, ecc. Potrebbe valere la pena considerare le esigenze di utilizzo dell'applicazione per l'inserimento, la cancellazione e l'accesso e scegliere una struttura più specializzata.

Si noti inoltre che se si desidera aggiungere elementi a un array ordinato di n elementi, una buona idea potrebbe essere quella di ordinare in modo efficiente gli elementi m , quindi unire i due array; inoltre, le matrici ordinate possono essere costruite in modo efficiente usando ad es. heap (ordinamento di heap).mnm


1
"Una tabella hash potrebbe avere O (1) inserzioni ed eliminazioni" - di solito ammortizzate.
Raffaello

8
Ammortamento previsto .
JeffE,

BST ha per la ricerca e l'inserimento (wikipedia), quindi perché non è la migliore scelta qui? O ( 2 l o gO(log n) per cercare e inserire. O(2 log n)
Kashyap,

8

Se hai qualche motivo per non usare l'heap, prendi in considerazione l'uso di Insertion Sort invece di Bubble Sort. È meglio quando hai alcuni elementi non ordinati.


8

Poiché stai usando un array, costa inserire un elemento - quando aggiungi qualcosa al centro di un array, ad esempio, devi spostare tutti gli elementi dopo di esso di uno in modo che l'array rimanga ordinato .O(n)

Il modo più veloce per scoprire dove posizionare l'oggetto è come hai menzionato, una ricerca binaria, che è , quindi la complessità totale sarà O ( n + lg n ) , che è nell'ordine diO(lgn)O(n+lgn) .O(n)

Detto questo, se mi sentissi particolarmente snarky, potrei sostenere che puoi "aggiungere un array ordinato" in O(1)

Ad ogni modo, non vedo alcun motivo per estrarre la bolla per questo problema.


2
O

+1 per essere snarky .. :-)
Kashyap

4

Patrick87 ha spiegato tutto molto bene. Ma un'ulteriore ottimizzazione che potresti fare sarebbe quella di usare qualcosa come un buffer circolare: puoi spostare gli oggetti a destra della posizione dell'elemento inserito a destra, come al solito. Ma puoi anche spostare gli oggetti a sinistra della posizione corretta a sinistra. Per fare ciò, è necessario considerare l'array come circolare, ovvero l'ultimo elemento si trova proprio prima del primo e richiede anche di mantenere l'indice da cui gli elementi attualmente iniziano.

Se lo fai, potrebbe significare che fai circa la metà del numero di accessi ad array (supponendo una distribuzione uniforme degli indici in cui inserisci). Nel caso di fare una ricerca binaria per trovare la posizione, è banale scegliere se spostarsi a sinistra o a destra. Nel caso dell'ordinamento a bolle, è necessario "indovinare" correttamente prima di iniziare. Ma farlo è semplice: basta confrontare l'elemento inserito con la mediana dell'array, che può essere fatto con un singolo accesso all'array.


4

Ho usato l' algoritmo di ordinamento Insertion in modo efficace per questo problema. Una volta abbiamo avuto un problema di prestazioni con un oggetto tabella hash, ho scritto un nuovo oggetto che utilizzava la ricerca binaria invece di aumentare significativamente le prestazioni. Per mantenere ordinato l'elenco, tenere traccia del numero di elementi aggiunti dall'ultimo ordinamento (ovvero il numero di elementi non ordinati) quando l'elenco doveva essere ordinato a causa di una richiesta di ricerca, eseguiva un ordinamento di inserimento o un ordinamento rapido a seconda sulla percentuale di articoli non ordinati. L'uso dell'ordinamento per inserzione è stato fondamentale per migliorare le prestazioni.


Avete un risultato formale per quanto riguarda i costi operativi ammortizzati? E: benvenuto!
Raffaello
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.