First of all, the reason it forgets to replace certain items is probably that $hget(table,%id) does not do what you think: $hget(table,3) does not return the data of the 3rd item, it returns the data of the item named "3". Compare with $hget(table,3).item (and $hget(table,3).data). So unless all your items names are consecutive numbers from 1 to $hget(table,0).item, things will go wrong.
You could first get the item name from the index with something like
var %name = $hget(table,%id).item
and change $hget(%table,%id) to to $hget(%table,%name) but be aware that this will slow down your script considerably ($hget().item/data is not an efficient way to access a hash table).
Also, not sure if you created all those variables just for testing purposes, but your script would run somewhat faster if you got rid of most of them. Here's what I mean (the following does not address the first problem):
var %cnt = 1, %ttl = $hget(table,0).item
while %cnt <= %ttl {
hadd table %cnt $puttok($hget(table,%cnt),Melon,5,9)
inc %cnt
}