Rather than trying to write a new article on an already well covered topic see the wikipedia article on hash functions. In particular the first image clearly shows how multiple inputs are hashed to the same value.
Basically, your triplet is hashed to some hash value in the range [0,2^64 - 1] (duplicates allowed!). Then the range is reduced to something slightly larger than your number of input values (say n=5) via the equation hash = hash % n. The resulting relation for input values of say [(1,1,1), (1,2,3), (2321, 322, 232), (3,3,3)] will then look something like this:
(1,1,1) -> 2
(1,2,3) -> 0
(2321, 322, 232) -> 0
(3,3,3) -> 3
As you can see no input value relates (i.e. hashes) to 1 or 4 and there are two input values hashing to 0.
The power of the hash (and the reason the average case is O(1)) is made clear by noting that in order to retrieve an input value from the hash table (e.g. (1,1,1)) the following steps occur.
- Input value's hash is calculated and
hash = hash % n
is applied, therefore (1,1,1) -> 2.
- A direct O(1) lookup is performed, i.e.
hash_function[2] = (1,1,1) + additional data stored with this particular input value
.
- Done!
In the case where more than one input value maps to the same hash value (0 in our example), the internal algorithm needs to do a search on those input values which is often done using a red-black tree (worst case O(log n)
). The worst case for any lookup is thus also O(log n)
.
A perfect hash occurs when the relation becomes a one-to-one onto function (a bijection). This gives best performance but is rare. As I stated earlier, luckily it is easy to produce an almost perfect hash where duplicates are scarce. In essence make your hash function as random as possible.
The examples I gave in the comments might be adequate (and the wrong way to do it ): ) but a more standard caculation would be: hash = ((((prime1 + value1) * prime2) + value2) * prime3) + value3) * prime4
which also answers the question. Note that the prime numbers can be any prime but usually small values like 31,37, etc. are used in practice.
In practice testing can be used to check the performance but is usually not necessary.
In any case re-reading your question I am wondering why you are not dropping the entire hash idea and not just store your points in a simple array??