CS106B Assignment7

Foreword

记录2022 winter的CS106B Assignment7

Enumerations Warmup

熟悉一下枚举类型

Linear Probing Warmup

熟悉一下线性探测哈希

Implementing Linear Probing

实现LinearProbingHashTable.h

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
#include "LinearProbingHashTable.h"
using namespace std;

LinearProbingHashTable::LinearProbingHashTable(HashFunction<string> hashFn) {
myHash = hashFn;
allocatedSize = hashFn.numSlots();
elems = new Slot[allocatedSize];
for (int i = 0; i < allocatedSize; ++i) {
elems[i].type = SlotType::EMPTY;
}
}

LinearProbingHashTable::~LinearProbingHashTable() {
delete[] elems;
}

int LinearProbingHashTable::size() const {
return logicalSize;
}

bool LinearProbingHashTable::isEmpty() const {
return logicalSize == 0;
}

bool LinearProbingHashTable::insert(const string& elem) {
int hash = myHash(elem) % allocatedSize;
while (true) {
if (logicalSize == allocatedSize) {
return false;
} else if (elems[hash].type == SlotType::EMPTY) {
elems[hash].value = elem;
elems[hash].type = SlotType::FILLED;
++logicalSize;
return true;
} else if (elems[hash].type == SlotType::FILLED) {
if (elems[hash].value == elem) {
return false;
}
} else if (elems[hash].type == SlotType::TOMBSTONE) {
if (!contains(elem)) {
elems[hash].value = elem;
elems[hash].type = SlotType::FILLED;
++logicalSize;
return true;
}
}
hash = (hash + 1) % allocatedSize;
}
}

bool LinearProbingHashTable::contains(const string& elem) const {
int hash = myHash(elem) % allocatedSize;
int T = logicalSize;
while (T) {
if (elems[hash].type == SlotType::FILLED && elems[hash].value == elem) {
return true;
} else if (elems[hash].type == SlotType::EMPTY) {
break;
} else if (elems[hash].type == SlotType::FILLED) {
--T;
}
hash = (hash + 1) % allocatedSize;
}
return false;
}

bool LinearProbingHashTable::remove(const string& elem) {
if (!contains(elem)) {
return false;
}
int hash = myHash(elem) % allocatedSize;
int T = logicalSize;
while (T) {
if (elems[hash].type == SlotType::EMPTY) {
return false;
} else if (elems[hash].type == SlotType::FILLED) {
if (elems[hash].value == elem) {
--logicalSize;
elems[hash].value.clear();
elems[hash].type = SlotType::TOMBSTONE;
return true;
}
--T;
}
hash = (hash + 1) % allocatedSize;
}
return false;
}

Robin Hood Warmup

熟悉一下Robin Hood哈希

主要思想是让每个key离它的home slot尽量近

Robin Hood Hashing

实现RobinHoodHashTable.h

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
#include "RobinHoodHashTable.h"
using namespace std;

RobinHoodHashTable::RobinHoodHashTable(HashFunction<string> hashFn) {
myHash = hashFn;
allocatedSize = hashFn.numSlots();
elems = new Slot[allocatedSize];
for (int i = 0; i < allocatedSize; ++i) {
elems[i].distance = EMPTY_SLOT;
}
}

RobinHoodHashTable::~RobinHoodHashTable() {
delete[] elems;
}

int RobinHoodHashTable::size() const {
return logicalSize;
}

bool RobinHoodHashTable::isEmpty() const {
return logicalSize == 0;
}

bool RobinHoodHashTable::insert(const string& elem) {
if (contains(elem) || logicalSize == allocatedSize) {
return false;
}
int hash = myHash(elem) % allocatedSize;
int dis = 0;
while (true) {
if (elems[hash].distance == EMPTY_SLOT) {
++logicalSize;
elems[hash].value = elem;
elems[hash].distance = dis;
return true;
} else if (elems[hash].distance < dis) {
auto hostage = elems[hash].value;
elems[hash].value = elem;
elems[hash].distance = dis;
insert(hostage);
return true;
}
++dis;
hash = (hash + 1) % allocatedSize;
}
return false;
}

bool RobinHoodHashTable::contains(const string& elem) const {
if (logicalSize == 0) {
return false;
}
int hash = myHash(elem) % allocatedSize;
int dis = 0;
while (true) {
if (elems[hash].distance == EMPTY_SLOT) {
return false;
} else if (elems[hash].value == elem) {
return true;
} else if (elems[hash].distance < dis) {
return false;
}
++dis;
hash = (hash + 1) % allocatedSize;
}
}

bool RobinHoodHashTable::remove(const string& elem) {
if (!contains(elem) || logicalSize == 0) {
return false;
}
int hash = myHash(elem) % allocatedSize;
while (true) {
if (elems[hash].value == elem) {
elems[hash].distance = EMPTY_SLOT;
elems[hash].value.clear();
--logicalSize;
while (true) {
int nxt = (hash + 1) % allocatedSize;
if (elems[nxt].distance == EMPTY_SLOT || elems[nxt].distance == 0) {
elems[hash].distance = EMPTY_SLOT;
elems[hash].value.clear();
break;
}
elems[hash].value = elems[nxt].value;
elems[hash].distance = elems[nxt].distance - 1;
hash = nxt;
}
return true;
}
hash = (hash + 1) % allocatedSize;
}
return false;
}

效果

性能分析