-
Notifications
You must be signed in to change notification settings - Fork 1
/
MyMap.h
255 lines (211 loc) · 4.41 KB
/
MyMap.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
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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
#ifndef MYMAP_INCLUDED
#define MYMAP_INCLUDED
#include <iostream>
#include <string>
#include <queue>
template <class KeyType, class ValueType>
class MyMap
{
private:
struct BSTNODE
{
// By definition the BSTNODE constructor will only be called with parameters given
BSTNODE(KeyType keyInit, ValueType valueInit)
{
left = right = parent = nullptr;
key = keyInit;
value = valueInit;
}
BSTNODE* left;
BSTNODE* right;
BSTNODE* parent;
KeyType key;
ValueType value;
};
public:
MyMap()
{
m_root = nullptr;
m_nodeCounter = 0;
// Initialize m_valid to false since the tree is empty upon calling the constructor.
m_valid = false;
}
~MyMap()
{
clear();
}
void clear()
{
BSTNODE* temp = m_root;
freeTree(temp);
m_root = nullptr;
m_nodeCounter = 0;
}
int size() const
{
return m_nodeCounter;
}
void associate(const KeyType& key, const ValueType& value)
{
// Check if tree is empty
if (m_root == nullptr)
{
BSTNODE* temp = new BSTNODE(key, value);
m_root = temp;
m_nodeCounter++;
m_valid = true;
return;
}
BSTNODE* cur = m_root;
for (;;)
{
// Duplicate values will be swapped for the newest value
if (key == cur->key)
{
cur->value = value;
return;
}
else if (key < cur->key)
{
if (cur->left != nullptr)
cur = cur->left;
else
{
BSTNODE* newNode = new BSTNODE(key, value);
cur->left = newNode;
newNode->parent = cur;
m_nodeCounter++;
return;
}
}
else // key > cur->key
{
if (cur->right != nullptr)
cur = cur->right;
else
{
BSTNODE* newNode = new BSTNODE(key, value);
cur->right = newNode;
newNode->parent = cur;
m_nodeCounter++;
return;
}
}
}
}
const ValueType* find(const KeyType& key) const
{
BSTNODE* cur = m_root;
while (cur != nullptr)
{
if (key == cur->key)
{
ValueType* valPtr;
valPtr = &cur->value;
return valPtr;
}
else if (key < cur->key)
cur = cur->left;
else
cur = cur->right;
}
return nullptr;
}
ValueType* find(const KeyType& key)
{
// Do not change the implementation of this overload of find
const MyMap<KeyType, ValueType>* constThis = this;
return const_cast<ValueType*>(constThis->find(key));
}
ValueType* getFirst(KeyType& key)
{
if (m_root == nullptr)
return nullptr;
BSTNODE* temp = m_root;
// Using a queue to complete a level-order traversal
addChildrenNodesToQueue(temp);
ValueType* getFirstValue;
getFirstValue = &temp->value;
key = temp->key;
return getFirstValue;
}
ValueType* getNext(KeyType& key)
{
if (m_traverseQueue.empty())
return nullptr;
// Dequeue top node pointer and process
BSTNODE* temp = m_traverseQueue.front();
addChildrenNodesToQueue(temp);
m_traverseQueue.pop();
ValueType* getValue;
getValue = &temp->value;
key = temp->key;
return getValue;
}
// Test printing
// TODO: Remove
void testPrintIndexInit()
{
// Object specific print function for MyMap <string, vector<HashedUrl> > instances
BSTNODE* cur = m_root;
testPrintIndex(cur);
}
void testPrintIndex(BSTNODE* cur)
{
if (cur == nullptr)
return;
testPrintIndex(cur->left);
// Print the key string
std::cerr << cur->key << " " << std::endl;
testPrintIndex(cur->right);
}
void testPrintInit()
{
BSTNODE* cur = m_root;
testPrint(cur);
}
void testPrint(BSTNODE* cur)
{
if (cur == nullptr)
return;
testPrint(cur->left);
std::cerr << cur->key << " " << cur->value << std::endl;
testPrint(cur->right);
}
private:
MyMap(const MyMap &other);
MyMap &operator=(const MyMap &other);
// Private methods
void freeTree(BSTNODE* cur);
bool isValid();
void addChildrenNodesToQueue(BSTNODE* cur);
// Private data members
BSTNODE* m_root;
unsigned int m_nodeCounter;
bool m_valid;
std::queue<BSTNODE*> m_traverseQueue;
};
// Externally defined functions
template <class KeyType, class ValueType>
void MyMap<KeyType, ValueType>::freeTree(BSTNODE* cur)
{
if (cur == nullptr)
return;
freeTree(cur->left);
freeTree(cur->right);
delete cur;
}
template <class KeyType, class ValueType>
bool MyMap<KeyType, ValueType>::isValid()
{
return m_valid;
}
template <class KeyType, class ValueType>
void MyMap<KeyType, ValueType>::addChildrenNodesToQueue(BSTNODE* cur)
{
if (cur->left != nullptr)
m_traverseQueue.push(cur->left);
if (cur->right != nullptr)
m_traverseQueue.push(cur->right);
}
#endif // MYMAP_INCLUDED