Existe esta estructura de datos que intercambia el rendimiento del acceso a la matriz frente a la necesidad de iterar sobre él al borrarlo. Mantiene un contador de generación con cada entrada, y también un contador de generación global. La operación "borrar" aumenta el contador de generación. En cada acceso, usted compara contadores de generación locales versus globales; si difieren, el valor se trata como "limpio".
Esto ha surgido en esta respuesta en Stack Overflow recientemente, pero no recuerdo si este truco tiene un nombre oficial. ¿Lo hace?
Un caso de uso es el algoritmo de Dijkstra si solo un pequeño subconjunto de los nodos tiene que ser relajado, y si esto tiene que hacerse repetidamente.
algorithms
terminology
krlmlr
fuente
fuente
Respuestas:
El enfoque antes mencionado requiere que cada celda pueda contener un número lo suficientemente grande como para contener el número de veces que la matriz puede necesitar reinicializarse, lo cual es una penalización de espacio sustancial. Si una ranura es capaz de contener al menos un valor que nunca se escribirá legítimamente, se puede evitar tener cualquier otra penalización de espacio (no constante) a expensas de agregar una
O(Wlg(N))
penalización de tiempo, dondeW
es el número de ranuras de matriz distintas escritas entre operaciones de limpieza yN
es el tamaño de la matriz. Por ejemplo, suponga que uno almacenará enteros de -2,147,483,647 a 2,147,483,647 (pero nunca -2,147,483,648) y quiere que los elementos de la matriz en blanco se lean como cero. Comience llenando la matriz con -2,147,483,648 (llame a ese valorB
) Cuando lea una ranura de matriz para la aplicación, informe un valor deB
cero. Antes de escribir ranura de matrizI
, comprobar si se llevó a caboB
y si es así, yI
es mayor que uno, almacena un cero a la ranuraI/4
después de realizar una comprobación similar para esa ubicación (y, si se llevó a caboB
,I/16
etc).Para borrar la matriz, comience con
I
0 o 1, dependiendo de la base de la matriz (el algoritmo como se describe funcionará para cualquiera de los dos). Luego repita el siguiente procedimiento: Si el ítemI
esB
, incrementeI
y, si lo hace, produce un múltiplo de cuatro, divida por cuatro (termine si la división produce un valor de 1); si el artículoI
no lo estáB
, guárdeloB
allí y multipliqueI
por cuatro (siI
comienza en cero, multiplicar por cuatro lo dejará en cero, pero como el artículo 0 estará en blanco,I
se incrementará).Tenga en cuenta que uno podría reemplazar la constante "cuatro" anterior con otros números, con valores más grandes que generalmente requieren menos etiquetado de trabajo, pero valores más pequeños generalmente requieren menos limpieza de trabajo; dado que los espacios de la matriz que están etiquetados tienen que borrarse, un valor de tres o cuatro es casi seguro óptimo; dado que el valor cuatro es ciertamente óptimo, es mejor que dos u ocho y es más conveniente que cualquier otro número, parece la opción más razonable.
fuente
Yo lo llamaría "reinicialización de células de matriz perezosa", pero no parece tener ningún nombre establecido (es decir, el nombre está en uso generalizado).
El algoritmo es inteligente, pero muy especializado y aplicable en un área muy estrecha.
fuente
Creo que es un caso especial de memorización , excepto en este caso, los "memorandos" implícitamente "envejecen" con cada incremento del contador global. Supongo que una especie de "memoria hacia atrás".
fuente