Existe essa estrutura de dados que negocia o desempenho do acesso ao array contra a necessidade de iterar sobre ele ao limpá-lo. Você mantém um contador de geração em cada entrada e também um contador de geração global. A operação "limpa" aumenta o contador de geração. Em cada acesso, você compara os contadores de geração local versus global; se eles diferem, o valor é tratado como "limpo".
Isso apareceu nesta resposta recentemente no Stack Overflow , mas não me lembro se esse truque tem um nome oficial. Faz isso?
Um caso de uso é o algoritmo de Dijkstra, se apenas um pequeno subconjunto dos nós precisar ser relaxado e se for necessário repetidamente.
algorithms
terminology
krlmlr
fonte
fonte
Respostas:
A abordagem mencionada acima exige que cada célula seja capaz de manter um número grande o suficiente para manter o número de vezes que a matriz pode precisar ser reinicializada, o que é uma penalidade de espaço substancial. Se um slot é capaz de armazenar pelo menos um valor que nunca será legitimamente gravado, é possível evitar qualquer outra penalidade de espaço (não constante) às custas da adição de uma
O(Wlg(N))
penalidade de tempo, ondeW
é o número de slots de matriz distintos gravados entre operações de limpeza eN
é o tamanho da matriz. Por exemplo, suponha que alguém armazene números inteiros de -2.147.483.647 a 2.147.483.647 (mas nunca -2.147.483.648) e deseje que os itens da matriz em branco sejam lidos como zero. Comece preenchendo a matriz com -2.147.483.648 (chame esse valorB
) Ao ler um slot de matriz para o aplicativo, relate um valorB
igual a zero. Antes de escrever slot de gamaI
, verifique se realizouB
e se assim eI
é maior que um, armazenar um zero a ranhuraI/4
após a realização de uma verificação semelhante para esse local (e, se realizadaB
,I/16
, etc).Para limpar a matriz, comece com
I
igual a 0 ou 1, dependendo da base da matriz (o algoritmo conforme descrito funcionará para ambos). Repita o procedimento a seguir: Se itemI
forB
, incrementeI
e, se isso resultar em um múltiplo de quatro, divida por quatro (termine se a divisão gerar um valor de 1); se o itemI
não estiverB
, armazeneB
-o e multiplique-oI
por quatro (seI
começar em zero, multiplicar por quatro deixará zero, mas como o item 0 ficará em branco,I
será incrementado).Observe que é possível substituir a constante "quatro" acima por outros números, com valores maiores geralmente exigindo menos marcação de trabalho, mas valores menores geralmente exigindo menos compensação de trabalho; como os slots de matriz marcados precisam ser limpos, um valor de três ou quatro é quase certamente ideal; como o valor quatro certamente está próximo do ideal, é melhor que dois ou oito e é mais conveniente do que qualquer outro número, parece a escolha mais razoável.
fonte
Eu chamaria isso de "reinicialização de célula de matriz lenta", mas parece não ter nenhum nome estabelecido (ou seja, o nome está sendo amplamente utilizado).
O algoritmo é inteligente, mas muito especializado e aplicável em uma área muito estreita.
fonte
Eu acredito que é um caso especial de memorização , exceto neste caso, os "memorandos" implicitamente "envelhecem" a cada incremento do contador global. Eu acho que uma espécie de "memorização reversa".
fonte