Vous pouvez faire tout cela en temps amorti prévu. L'astuce essentielle est que nous n'avons pas besoin de toute la puissance d'une file d'attente prioritaire, car la fréquence des clés ne change que de 1 lors de chaque insertion ou suppression.O(1)
Ma solution ci-dessous est vraiment votre solution avec une file d'attente prioritaire "inefficace" qui fonctionne bien dans ce cas: une file d'attente prioritaire maximale implémentée comme une liste doublement liée de compartiments de clés a O (1) insertMin, deleteMax, removeFromBucket et augmenter la clé.
Conservez une liste de compartiments doublement liée, où chaque compartiment a un ensemble de clés de hachage non vide (que j'appellerai une cohorte) et un entier positif (que j'appellerai le ValCount). Dans un compartiment b, chaque clé k de la cohorte de b a le même nombre de valeurs uniques qui lui sont associées dans l'ensemble que vous conservez. Par exemple, si votre ensemble contient les paires (a, pomme), (a, avocat), (b, banane), (c, concombre), (d, fruit du dragon) où les lettres simples sont les clés et les fruits sont les valeurs, vous auriez alors deux compartiments: un compartiment aurait un ValCount de 2 et une cohorte composée d'une seule clé: a. L'autre Bucket aurait un ValCount de 1 et une Cohorte composée des trois clés b, c et d.
La liste doublement liée de Bucket doit être conservée par le ValCount. Il sera important que nous puissions trouver la tête et la queue de la liste en temps et que nous pouvons épisser dans un nouveau Bucket en temps O ( 1 ) si nous connaissons ses voisins. Sans imagination, j'appellerai la liste des Buckets la BucketList.O(1)O(1)
En plus de BucketList, nous aurons besoin d'un SetMap, qui est une carte de hachage mappant les clés à ValueBuckets. Un ValueBucket est une paire composée du ValueSet (un ensemble de valeurs de hachage non vide) et d'un pointeur non nul vers un Bucket. Le ValueSet associé à une clé k contient toutes les valeurs uniques associées à k. Le pointeur Bucket associé à un ValueSet a une cohorte égale à la taille du ValueSet. Le Bucket associé à une clé k dans SetMap est également associé à la clé k dans BucketList.
En 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;
Pour trouver une paire clé-valeur de fréquence maximale, il suffit de regarder la tête de la BucketList, de trouver une clé dans la cohorte, de rechercher cette clé dans le SetMap et de trouver une valeur dans le ValueSet de son ValueBucket. (phew!)
L'insertion et la suppression de paires clé-valeur est plus délicate.
Pour insérer ou supprimer une paire clé-valeur, nous l'insérons ou la supprimons d'abord dans le SetMap Cela changera la taille du ValueSet, nous devons donc modifier le Bucket associé à la clé. Les seuls compartiments que nous devrons examiner pour effectuer ce changement seront les voisins immédiats du compartiment dans lequel se trouvait la clé. Il existe plusieurs cas ici, et ils ne valent probablement pas la peine d'être expliqués en détail, bien que je serais heureux d'élaborer si vous rencontrez toujours des problèmes.