Puoi fare tutto ciò nel tempo ammortizzato previsto per . Il trucco essenziale è che non abbiamo bisogno della piena potenza di una coda prioritaria, poiché la frequenza della chiave cambia solo di 1 durante ogni inserimento o cancellazione.O(1)
La mia soluzione di seguito è davvero solo la tua soluzione con una coda di priorità "inefficiente" che sembra funzionare bene in questo caso: una coda di massima priorità implementata come elenchi doppiamente collegati di secchi di chiavi ha O (1) insertMin, deleteMax, removeFromBucket e increaseKey.
Mantenere un elenco doppiamente collegato di bucket, in cui ogni bucket ha un set di chiavi hash non vuoto (che chiamerò una coorte) e un numero intero positivo (che chiamerò ValCount). In un bucket b, ogni chiave k nella coorte di b ha lo stesso numero di valori univoci associati ad essa nell'insieme che si sta mantenendo. Ad esempio, se il tuo set ha le coppie (a, mela), (a, avocado), (b, banana), (c, cetriolo), (d, frutto del drago) dove le singole lettere sono le chiavi e i frutti sono i valori, quindi avresti due bucket: un bucket avrebbe un ValCount di 2 e una coorte composta da una sola chiave: a. L'altro bucket avrebbe un ValCount pari a 1 e una coorte composta dalle tre chiavi b, c e d.
L'elenco doppiamente collegato di Bucket deve essere ordinato da ValCount. Sarà importante che possiamo trovare la testa e la coda della lista in tempo e che possiamo unire un nuovo Secchio in O ( 1 ) tempo se conosciamo i suoi vicini. Inimmaginabilmente, chiamerò la lista di Buckets la BucketList.O(1)O(1)
Oltre alla BucketList, avremo bisogno di una SetMap, che è una mappa di hash che associa le chiavi a ValueBuckets. Un ValueBucket è una coppia costituita da ValueSet (un set di valori hash non vuoto) e un puntatore non null a un bucket. ValueSet associato a una chiave k contiene tutti i valori univoci associati a k. Il puntatore Bucket associato a ValueSet ha una coorte uguale alla dimensione di ValueSet. Il bucket associato a una chiave k in SetMap è anche associato alla chiave k in BucketList.
In C ++:
struct Bucket {
unsigned ValCount;
unordered_set<Key> Cohort;
Bucket * heavier;
Bucket * lighter;
};
Bucket * BucketListHead;
Bucket * BucketListTail;
struct ValueBucket {
unordered_set<Value> ValueSet;
Bucket * bucket;
};
unordered_map<Key, ValueBucket> SetMap;
Per trovare una coppia chiave-valore di frequenza massima, dobbiamo solo guardare in testa alla BucketList, trovare una chiave nella Coorte, cercare quella chiave in SetMap e trovare un valore nel ValueSet del suo ValueBucket. (Uff!)
Inserire ed eliminare le coppie chiave-valore è più complicato.
Per inserire o eliminare una coppia chiave-valore, dobbiamo prima inserirla o eliminarla in SetMap Questo cambierà la dimensione del ValueSet, quindi dobbiamo modificare la Bucket associata alla chiave. Gli unici bucket che dovremo esaminare per apportare questo cambiamento saranno i vicini immediati del bucket in cui si trovava la chiave. Ci sono diversi casi qui, e probabilmente non valgono la pena spiegarli completamente, anche se sarei felice per capire se hai ancora problemi.