-
Notifications
You must be signed in to change notification settings - Fork 0
/
DoubleHashing.cs
133 lines (118 loc) · 3.6 KB
/
DoubleHashing.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
// 23521 - Gustavo Cruz
using System;
using System.Collections.Generic;
// A hash table class that uses double hashing for hashing
public class DoubleHashing<T> : IHashTable<T>
where T : IRegistry<T>
{
private int physicalSize = 131;
private int logicalSize = 0;
private T[] data;
public DoubleHashing()
{
data = new T[physicalSize];
}
/*
* +------------------------------------------------------------+
* | Determines the hash value of a key based on double hashing |
* +------------------------------------------------------------+
*
* Multiple succesive hashes are performed on a previous calculated hash value
* untill an empty position is found in the hash table.
*/
public int Hash(string key)
{
// Calculates the initial hash value
long hash = 0;
foreach (char c in key)
hash += 37 * hash + c;
hash %= physicalSize;
if (hash < 0)
hash += physicalSize;
int initialPosition = (int)hash;
int currentPosition = initialPosition;
int collisions = 0;
// Inspects each position of the hash table
while (data[currentPosition] != null)
{
// Found an object with the same key
if (data[currentPosition].Key == key)
return currentPosition;
// Keep looking for an empty spot
currentPosition = currentPosition + collisions * (13 - currentPosition % 13);
collisions++;
}
return currentPosition;
}
public int ResizeTable(int physicalSize)
{
physicalSize = physicalSize * 2 + 1;
while (!isPrime(physicalSize))
physicalSize++;
return physicalSize;
}
public void ReHash()
{
physicalSize = ResizeTable(physicalSize);
logicalSize = 0;
List<T> objects = Content();
data = new T[physicalSize];
foreach (T obj in objects)
Insert(obj);
}
public bool Insert(T item)
{
// If hash table is more than half full, rehash it to proceed with insertion
if (logicalSize >= physicalSize / 2)
ReHash();
int itemPosition;
// Object already inserted in the hash table
if (Exists(item, out itemPosition))
return false;
if (data[itemPosition] != null)
{
// Prevents overriding between objects with the same key
if (data[itemPosition].Key == item.Key)
return false;
// Prevents overriding a different object
if (data[itemPosition].Key != item.Key)
return false;
}
data[itemPosition] = item;
logicalSize++;
return true;
}
public bool Remove(T item)
{
int itemPosition;
if (Exists(item, out itemPosition))
{
data[itemPosition] = default;
logicalSize--;
return true;
}
return false;
}
public bool Exists(T item, out int itemPosition)
{
itemPosition = Hash(item.Key);
if (data[itemPosition] == null)
return false;
return data[itemPosition].Equals(item);
}
public List<T> Content()
{
List<T> content = new List<T>();
foreach (T item in data)
if (item != null)
content.Add(item);
return content;
}
public bool isPrime(int physicalSize)
{
for (int i = 2; i < Math.Sqrt(physicalSize); i++)
if (physicalSize % i == 0)
return false;
return true;
}
}