Skip to content

Commit c911967

Browse files
committed
Hashing deletion, dynamic table size
1 parent 683f28e commit c911967

File tree

2 files changed

+221
-0
lines changed

2 files changed

+221
-0
lines changed
Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
import parse from '../../pseudocode/parse';
2+
3+
4+
// XXX Best skip NullTable and HashInit function completely - just start
5+
// animation with initialised table
6+
// XXX: if dynamic tables are not implemented, both CheckTableFullness
7+
// and CheckTableFullness should be removed
8+
// NOTE: code now no longer explicitly keeps track of number of
9+
// insertions and CheckTableFullness is modified so some bookmarks (eg,
10+
// 4, 19, 20) no longer exist and controller code will have to change
11+
const main = `
12+
13+
\\Code{
14+
NullTable
15+
i <- 0
16+
while i<TableSize \\B 2
17+
\\In{
18+
T[i] <- Empty // Table must start with all slots empty
19+
i <- i+1
20+
\\In}
21+
\\Code}
22+
23+
\\Code{
24+
Main
25+
HashInit(T) // TableSize is prime \\B 1
26+
\\In{
27+
Initialize Hash Table Slots to Empty \\Ref NullTable
28+
Insertions <- 0 // Keep track of how full table is \\B 3
29+
\\In}
30+
31+
//=======================================================
32+
33+
HashInsert(T, k) // Insert key k into table
34+
\\In{
35+
Check how full the table is \\Ref CheckTableFullness
36+
\\Expl{ One empty slot must always be maintained, to
37+
prevent infinite loops when searching.
38+
Performance also degrades with fewer empty slots and we may want to reconstruct the table with a larger size.
39+
See Background for more details.
40+
\\Expl}
41+
\\Note{The following has a choose increment value -- assumes we can make a choice
42+
here between linear probing and double hashing. NOTE TO DEVELOPERS: We are planning to
43+
make linear probing and double hashing as two separate modules.
44+
So -- in the linear probing pseudocode there is no "Choose increment",
45+
increment is just 1, and further on in the pseudocode Increment will be replaced
46+
by 1. For the double hashing, we need to calculate the second hash function.
47+
\\Note}
48+
i <- hash(k) \\Ref Hash1
49+
Choose Increment value in case of collisions \\Ref SetIncrement
50+
Search for unoccupied slot \\Ref InsertionLoop
51+
\\Expl{ Check slots in steps of the chosen increment value, wrapping around at the end of the table
52+
\\Expl}
53+
T[i] <- k // unoccupied slot found so we put k in it \\B 9
54+
// Done \\B 10
55+
\\In}
56+
57+
//=======================================================
58+
59+
HashDelete(T, k) // Delete key k in table T \\B 11
60+
\\In{
61+
Check how full the table is \\Ref CheckTableFullnessDel
62+
\\Expl{ If there are lots of Deleted slots we may want to reconstruct the table to improve performance.
63+
\\Expl}
64+
i <- hash(k) // Expand Hash in HashInsert for details \\B 16
65+
Choose Increment value for stepping through T //Expand ChooseIncrement in HashInsert for details \\B 17
66+
while not (T[i] = k or T[i] = Empty or T[i] = Deleted) // search for k or Empty or Deleted \\B 12
67+
\\In{
68+
i <- (i + Increment) mod TableSize \\B 13
69+
\\Expl{ T[i] is not k or Empty so we jump ahead Increment
70+
steps and "wrapping around" if we reach the end, mirroring
71+
the insertion code.
72+
\\Expl}
73+
\\In}
74+
if T[i] = k \\B 14
75+
\\In{
76+
T[i] <- Deleted \\B 15
77+
\\Expl{ If T[i] contains the index element, the slot is flagged as deleted.
78+
We display "X" to indicate Deleted slots.
79+
\\Expl}
80+
\\In}
81+
else \\B 18
82+
\\In{
83+
// Do nothing
84+
\\In}
85+
\\In}
86+
\\Code}
87+
88+
\\Code{
89+
InsertionLoop
90+
\\Expl{ If T[i] = k then k already exists in the table. We could explicitly check
91+
for this but the code here simply over-writes the previous
92+
ocurrence of k, as if the slot was empty.
93+
\\Expl}
94+
while T[i] is occupied by another element // search for unoccupied slot \\B 7
95+
\\Expl{ If T[i] = k then k already exists in the table. We could explicitly check
96+
for this but the code here simply over-writes the previous
97+
ocurrence of k, as if the slot was empty.
98+
\\Expl}
99+
\\In{
100+
i <- (i + Increment) mod TableSize \\B 8
101+
\\Expl{ T[i] is occupied so we jump ahead Increment steps.
102+
We use modulo TableSize to "wrap around" if we reach the end.
103+
\\Expl}
104+
\\In}
105+
\\Code}
106+
107+
\\Code{
108+
CheckTableFullness
109+
if there are too few empty slots \\B 19
110+
\\Expl{ A small number of empty slots leads to poor performance.
111+
To overcome this we must construct a new (possibly
112+
larger) table and insert all the elements of T.
113+
This also gets rid of deleted slots.
114+
\\Expl}
115+
\\In{
116+
Create a new empty table T1
117+
\\Expl{ Without deleted elements, it is best for
118+
the table size to approximately double. If there are many deleted slots
119+
it may be OK to keep the same size.
120+
\\Expl}
121+
Insert each key in T into T1
122+
\\Note{ Animation can stop at this line for each
123+
key (could possibly have an extra level of expansion)
124+
\\Note}
125+
T <- T1
126+
\\In}
127+
\\Code}
128+
\\Code{
129+
CheckTableFullnessDel
130+
if there are too many deleted slots \\B 19
131+
\\Expl{ A small number of empty slots leads to poor performance.
132+
To overcome this we must construct a new table, which gets rid of deleted slots.
133+
It may also be worthwhile to reduce the table size.
134+
\\Expl}
135+
\\In{
136+
Create a new empty table T1
137+
\\Expl{ If there are many deleted slots
138+
it may be be worthwhile to reduce the table size.
139+
\\Expl}
140+
Insert each key in T into T1
141+
\\Expl{ For better performance we could omit inserting k here and skip the later HashDelete code.
142+
\\Expl}
143+
\\Note{ Animation can stop at this line for each
144+
key (could possibly have an extra level of expansion)
145+
\\Note}
146+
T <- T1
147+
\\In}
148+
\\Code}
149+
`
150+
export const hash1 = `
151+
\\Code{
152+
Hash1
153+
i <- (k * BIGPRIME) mod TableSize \\B 5
154+
\\Expl{ BIGPRIME much bigger than TableSize (which is also prime).
155+
The object is to spread the values across the hash table as widely as possible.
156+
Here we use BIGPRIME = 3457
157+
\\Expl}
158+
\\Code}
159+
`
160+
export const linearProbingIncrement = `
161+
162+
\\Code{
163+
SetIncrement
164+
Increment <- 1 \\B 6
165+
\\Expl{ For linear probing, if we have a collision we successively look at the
166+
next table entry.
167+
\\Expl}
168+
\\Code}
169+
170+
`
171+
172+
export const doubleHashingIncrement = `
173+
174+
\\Code{
175+
SetIncrement
176+
Increment <- (k * BIGPRIME2) mod SMALLISHPRIME + 1 \\B 6
177+
\\Expl{Double hashing resolves collisions by hashing the key k a second time to set the increment
178+
to find the next empty slot in the table R. The value given by the function must be non-zero
179+
and must also be relatively prime to the table size.
180+
Here BIGPRIME2 is 1429 and SMALLISHPRIME is 3 or 23, depending on the table size selected.
181+
\\Expl}
182+
\\Code}
183+
`
184+
export const doubleHashing = parse(main + hash1 + '\n' + doubleHashingIncrement);
185+
export const linearProbing = parse(main + hash1 + '\n' + linearProbingIncrement);
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import parse from '../../pseudocode/parse';
2+
import {
3+
linearProbingIncrement,
4+
doubleHashingIncrement,
5+
hash1
6+
} from './HashingInsertion'
7+
8+
let main = `
9+
\\Code{
10+
Main
11+
HashSearch(T, k) // Search for key k in table T \\B 1
12+
\\In{
13+
i <- hash(k) \\Ref Hash1
14+
Choose Increment value for stepping through T \\Ref SetIncrement
15+
while not (T[i] = k or T[i] = Empty or T[i] = Deleted) // search for T or Empty or Deleted \\B 2
16+
\\In{
17+
i <- (i + Increment) mod TableSize \\B 3
18+
\\Expl{ T[i] is not k or Empty so we jump ahead Increment
19+
steps and "wrapping around" if we reach the end, mirroring
20+
the insertion code.
21+
\\Expl}
22+
\\In}
23+
if T[i] = k \\B 4
24+
\\In{
25+
return i // return the table index where the key has been found \\B 7
26+
\\In}
27+
else
28+
\\In{
29+
return NOTFOUND \\B 8
30+
\\In}
31+
\\In}
32+
\\Code}
33+
`
34+
35+
export const doubleSearch = parse(main + '\n' + hash1 + '\n' + doubleHashingIncrement);
36+
export const linearSearch = parse(main + '\n' + hash1 + '\n' + linearProbingIncrement);

0 commit comments

Comments
 (0)