Puedes hacer todo esto en tiempo amortizado esperado. El truco esencial es que no necesitamos toda la potencia de una cola prioritaria, ya que la frecuencia clave solo cambia en 1 durante cada inserción o eliminación.O ( 1 )
Mi solución a continuación es realmente su solución con una cola de prioridad "ineficiente" que funciona bien para este caso: una cola de prioridad máxima implementada como listas doblemente vinculadas de cubos de claves tiene O (1) insertMin, deleteMax, removeFromBucket, y aumentar la clave.
Mantenga una lista doblemente vinculada de Buckets, donde cada Bucket tiene un conjunto de claves hash no vacías (que llamaré Cohorte) y un número entero positivo (que llamaré ValCount). En un Bucket b, cada clave k en la Cohorte de b tiene el mismo número de valores únicos asociados en el conjunto que está manteniendo. Por ejemplo, si su conjunto tiene los pares (a, manzana), (a, aguacate), (b, plátano), (c, pepino), (d, fruta del dragón) donde las letras individuales son las claves y las frutas son los valores, entonces tendría dos Buckets: un Bucket tendría un ValCount de 2 y una Cohorte que constaría de una sola clave: a. El otro Bucket tendría un ValCount de 1 y una Cohorte que constaría de las tres teclas b, c y d.
ValCount debe mantener ordenada la lista doblemente vinculada de Bucket. Será importante que podamos encontrar el encabezado y la cola de la lista en el tiempo y que podamos empalmar en un nuevo Cubo en O (O ( 1 ) si conocemos a sus vecinos. Inimaginablemente, llamaré a la lista de Buckets la BucketList.O ( 1 )
Además de BucketList, necesitaremos un SetMap, que es un mapa de claves de asignación de hash a ValueBuckets. Un ValueBucket es un par que consiste en el ValueSet (un conjunto de valores hash no vacío) y un puntero no nulo a un Bucket. El ValueSet asociado con una clave k contiene todos los valores únicos asociados con k. El puntero del depósito asociado con un ValueSet tiene una Cohorte igual al tamaño del ValueSet. El Bucket asociado con una clave k en SetMap también está asociado con la clave k en 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;
Para encontrar un par clave-valor de frecuencia máxima, solo tenemos que mirar el encabezado de la lista de cubo, encontrar una clave en la cohorte, buscar esa clave en el SetMap y encontrar un valor en el ValueSet de su ValueBucket. (¡Uf!)
Insertar y eliminar pares clave-valor es más complicado.
Para insertar o eliminar un par clave-valor, primero lo insertamos o eliminamos en el SetMap Esto cambiará el tamaño del ValueSet, por lo que debemos modificar el Bucket asociado con la clave. Los únicos Buckets que tendremos que mirar para hacer este cambio serán los vecinos inmediatos del Bucket en el que solía estar la llave. Hay varios casos aquí, y probablemente no valga la pena explicarlos completamente, aunque estaría feliz para elaborar si todavía tienes problemas.