Invece della semplice numerazione, è possibile distribuire i numeri su un intervallo ampio (di dimensioni costanti), come minimo intero e massimo di un intero CPU. Quindi puoi continuare a mettere i numeri "in mezzo" calcolando la media dei due numeri circostanti. Se i numeri diventano troppo affollati (ad esempio si finiscono con due numeri interi adiacenti e non c'è un numero in mezzo), è possibile effettuare una rinumerazione una tantum dell'intero ordine, ridistribuendo i numeri uniformemente nell'intervallo.
Ovviamente, puoi imbatterti nella limitazione che vengono utilizzati tutti i numeri all'interno dell'intervallo della costante grande. In primo luogo, questo non è di solito un problema, poiché la dimensione intera su una macchina è abbastanza grande in modo che se avessi più elementi probabilmente non rientrerebbe nella memoria. Ma se si tratta di un problema, puoi semplicemente rinumerarli con un intervallo intero più ampio.
Se l'ordine di input non è patologico, questo metodo potrebbe ammortizzare le rinumerazioni.
Rispondere alle domande
Un semplice confronto di numeri interi può rispondere alla query ( X<?Y).
Il tempo di query sarebbe molto rapido ( O ( 1 )) se si utilizzano numeri interi macchina, poiché si tratta di un semplice confronto di numeri interi. L'uso di un intervallo più ampio richiederebbe numeri più grandi e il confronto richiederebbeO ( log| intege r | ).
Inserimento
Innanzitutto, manterrai l'elenco collegato dell'ordine, mostrato nella domanda. Inserimento qui, dati i nodi per posizionare il nuovo elemento in mezzo, sarebbeO ( 1 ).
L'etichettatura del nuovo elemento sarebbe in genere rapida O ( 1 )perché calcoleresti facilmente il nuovo numero calcolando la media dei numeri circostanti. Occasionalmente potresti rimanere senza numeri "in mezzo", il che innescherebbe ilO ( n ) procedura di rinumerazione del tempo.
Evitare la rinumerazione
Puoi usare float invece di numeri interi, quindi quando ottieni due numeri interi "adiacenti", possono essere mediati. In questo modo puoi evitare di rinumerare di fronte a due float interi: basta dividerli a metà. Tuttavia, alla fine il tipo a virgola mobile avrà una precisione insufficiente e non sarà possibile calcolare la media di due galleggianti "adiacenti" (la media dei numeri circostanti sarà probabilmente uguale a uno dei numeri circostanti).
Allo stesso modo è possibile utilizzare un numero intero "decimale", in cui si mantengono due numeri interi per un elemento; uno per il numero e uno per il decimale. In questo modo, è possibile evitare la rinumerazione. Tuttavia, il numero intero decimale alla fine trabocca.
L'uso di un elenco di numeri interi o bit per ciascuna etichetta può evitare del tutto la rinumerazione; questo equivale sostanzialmente all'utilizzo di numeri decimali con lunghezza illimitata. Il confronto verrebbe effettuato in termini lessicografici e i tempi di confronto aumenteranno fino alla lunghezza degli elenchi interessati. Tuttavia, questo può sbilanciare l'etichettatura; alcune etichette potrebbero richiedere solo un numero intero (senza decimali), altre potrebbero avere un elenco di lunghezze (decimali lunghi). Questo è un problema, e la rinumerazione può aiutare anche qui, ridistribuendo la numerazione (qui elenchi di numeri) in modo uniforme su un intervallo scelto (intervallo qui che probabilmente significa lunghezza di elenchi) in modo che dopo tale rinumerazione, gli elenchi abbiano tutti la stessa lunghezza .
Questo metodo è effettivamente utilizzato in questo algoritmo ( implementazione , struttura dei dati rilevanti ); nel corso dell'algoritmo, è necessario mantenere un ordinamento arbitrario e l'autore utilizza numeri interi e rinumerazione per eseguire ciò.
Cercare di attenersi ai numeri rende lo spazio delle chiavi un po 'limitato. Si potrebbero invece usare stringhe a lunghezza variabile, usando la logica di confronto "a" <"ab" <"b". Rimangono ancora due problemi da risolvere A. Le chiavi potrebbero diventare arbitrariamente lunghe B. Il confronto delle chiavi lunghe potrebbe diventare costoso