Heap.Update (gb.data)
Sub Update ( Old As Variant, New As Variant )
Encontra todas as ocorrências
Old
e substitui por
New
. Esta é uma operação O(n).
Além disso, a pilha tem que ser reconstruída, se, foi realizada
mais de uma substituição.
Se
New
é nulo, então a entrada será excluída.
A busca dos objetos é feita por identidade e
não usando o
método _compare(). "Por identidade" significa que, se dois objetos são
comparados e ambos têm um método especial _identity() retornando uma Variant,
os valores de retorno desses métodos é que são comparados.
Se um dos objectos não implementa o método _identity(), o
padrão é a comparação por endereços de objetos na memória. Esta estratégia permite que
você salve tipos de dados primitivos (Integer, Boolean, String), etc. no
heap. Mas você também pode gerenciar objetos distintos em classes de equivalência: O método _compare()
define a sua relação de equivalência (como os objetos são mais ou menos ordenado no heap)
e a comparação identidade permite discernir objetos diferentes, mesmo da mesma classe (a fim de atualizá-los individualmente).
Se somos um amontoado de objetos cujos métodos _compare() comparam algum tipo de
prioridade, e
Old
é o mesmo objeto que
New
, este pode ser utilizado para
propagar uma mudança de prioridade feita para o objeto que vai corrigir a
posição no heap.
O método _identity() deixa isso para você o que a "identidade" realmente significa.
Se você precisa atualizar classes de equivalência inteiras de cada vez, você também pode definir
_identity() para combinar com seu método _compare ().
É um meio puramente opcional de agrupar objetos de forma diferente.
Aqui está um trecho pseudo-Gambas do algoritmo de comparação usado por Update:
Private Function Compare(Old As Variant, New As Variant) As Integer
If TypeOf(Old) <> gb.Object Or If TypeOf(New) <> gb.Object Then
Return CompareVariants(Old, New)
Else If HasIdentityFn(Old) And If HasIdentityFn(New) Then
Return CompareVariants(Old._identity(), New._identity())
Endif
Return Sgn(Object.Address(Old) - Object.Address(New))
End
Private Function HasIdentityFn(vValue As Variant) As Boolean
If Not TypeOf(vValue) = gb.Object Then Return False
' Queremos um método Public Function _identity() As Variant
Return Object.Class(vValue)["_identity"].Type = "v"
End
' CompareVariants é uma função que compara duas variantes com base nos
' tipos de dados de seus conteúdos. O núcleo interpretador sabe fazer isso.
Exemplo
Imagine que você está implementando o algoritmo de
Dijkstra (ou qualquer pesquisa de primeira prioridade
Like Prim ou A*). Você poderia usar um Heap para acompanhar a prioridade de seus nós.
Ao definir:
Public Sub _compare(hOther As Node) As Integer
Return Sgn(Me.Priority - hOther.Priority)
End
Primeiro você obtém os elementos de menor prioridade fora do heap (que é o que precisamos).
Quando necessário atualizar a prioridade de um nó e corrigir a sua posição na pilha, nós
não podemos utilizar o método _compare() para encontrar o nó porque muitos nós podem ter
a mesma prioridade e seria, portanto, indistinguíveis.
Aqui, você não precisa de um método _identity(). Para atualizar a prioridade da hNode a 17 e
corrigir a sua posição na pilha, você faz:
hNode.Priority = 17
hHeap.Update(hNode, hNode)