Algoritmo per aggiornare l'elenco ordinato prioritario in cui la modifica della priorità di un articolo è costosa

2

Sto lavorando contro un'API in cui posso aggiungere e aggiornare elementi in un elenco ordinato da un campo di priorità che posso impostare (che non deve essere contiguo ma deve essere un numero intero positivo).

L'aggiornamento di un membro della lista è un'operazione costosa, quindi voglio ridurre al minimo il numero di aggiornamenti.

Quello che voglio è un algoritmo che ridurrà al minimo il numero di aggiornamenti richiesti quando l'elenco viene riordinato.

vale a dire. Lo scenario peggiore per questo è usare priorità contigue a partire da 1. ad es.

Priority  | item
----------------
1           A
2           B
3           C
4           D
5           E

In questo caso per spostare l'elemento E in cima all'elenco, ogni singolo elemento dovrebbe avere la sua priorità aggiornata.

La soluzione ingenua che ho è di implementare grandi numeri per le priorità e inserire priorità che sono a metà dell'intervallo tra due elementi quando un articolo deve essere posizionato lì.

per es.

Priority  | item
----------------
1000000     A
2000000     B
3000000     C
4000000     D
5000000     E

In questo caso per spostare E verso l'alto è richiesto solo un aggiornamento (e posso impostare la sua priorità su 500000)

Il problema è che agirà come una ricerca binaria e anche nel caso in cui si utilizzino numeri iniziali dell'ordine di 10 ^ 9 saranno necessarie solo 30 operazioni finché le priorità non diventeranno contigue.

Esiste un algoritmo migliore di questo? C'è uno esistente che posso usare (ma non ho trovato tramite google), o qualcuno può suggerire un miglioramento a questo?

    
posta DanSingerman 08.10.2013 - 12:25
fonte

1 risposta

5

Se sei bloccato con la struttura dei dati dell'elenco

Se ti sforzi di minimizzare il numero di aggiornamenti prioritari, non puoi fare molto oltre l'approccio di ricerca binaria.

Altrimenti, un possibile piccolo miglioramento che mi viene in mente è che, ogni volta che inserisci un elemento C tra B e D, controlla l'elemento A in B ed E a destra di D e ridistribuisci le loro priorità.

Quindi per qualcosa di simile:

        C
        ↓
A B           D E
0 1           7 8

Finirai con:

A   B   C   D   E
0   2   4   6   8

Tieni presente che A e E non cambiano, le loro priorità sono solo obbligatorie nel calcolo.

Oppure puoi lasciare B dove si trova e aggiornare solo D , o viceversa, a seconda che A e D o B e E siano più distanti.

Se puoi selezionare un'altra struttura dati

Sarebbe preferibile sceglierne uno in cui la priorità è strutturalmente definita, non esplicitamente per ogni elemento.

Un albero di ricerca binario bilanciato modificato potrebbe funzionare qui, dove si memorizza il numero di antenati per ciascun nodo.

Il confronto per l'inserimento dovrebbe quindi essere definito esclusivamente sul punto in cui si desidera inserirlo rispetto ai conteggi di ciascun nodo.

Tieni presente che qualcosa come un albero rosso-nero non richiede alcun confronto per mantenersi in equilibrio.

Le operazioni di aggiornamento, inserimento ed eliminazione prenderanno tutte O(log n) .

A seconda delle tue esigenze, puoi avere una struttura dati secondaria che ti permette di cercare un nodo per un dato elemento.

    
risposta data 08.10.2013 - 15:58
fonte

Leggi altre domande sui tag