-
Notifications
You must be signed in to change notification settings - Fork 0
/
virus_genealogy.hpp
249 lines (209 loc) · 7.25 KB
/
virus_genealogy.hpp
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
#include <cstdio>
#include <exception>
#include <set>
#include <memory>
#include <map>
#include <vector>
#include <utility>
#include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp>
#include <boost/make_shared.hpp>
#ifndef VIRUS_GENEALOGY_H
#define VIRUS_GENEALOGY_H
class Virus;
class VirusAlreadyCreated : public std::exception {
public:
const char* what() const noexcept {
return "VirusAlreadyCreated";
}
};
class VirusNotFound : public std::exception {
public:
const char* what() const noexcept {
return "VirusNotFound";
}
};
class TriedToRemoveStemVirus : public std::exception {
public:
const char* what() const noexcept {
return "TriedToRemoveStemVirus";
}
};
template <class Virus>
class VirusGenealogy {
private:
//VirusGenealogy(VirusGenealogy &virgen) = delete;
//operator=(VirusGenealogy &virgen) = delete;
typedef typename Virus::id_type v_id;
//Klasa reprezentujaca wierzcholek, mamy set dzieci i set rodzicow
class Node {
private:
std::map<v_id, boost::weak_ptr<Node> > *nodes;
public:
v_id id; //ID wierzcholka
Virus *virus; //obiekt wirusa
std::set<boost::shared_ptr<Node> > children; //set dzieci
std::set<boost::weak_ptr<Node> > parents; //set rodzicow
boost::weak_ptr<Node> ja;
typename std::map<v_id, boost::weak_ptr<Node> >::iterator iterator_do_mnie;
Node(const v_id &newId, std::map<v_id, boost::weak_ptr<Node> > *extnodes):
id(newId),
virus(new Virus(newId))
{
nodes = extnodes;
}
~Node()
{
// usuwamy wskaznik do usuwanego wierzcholka z listy rodzicow u dzieci
for (boost::shared_ptr<Node> child : children)
{
child -> parents.erase(ja);
}
children.erase(children.begin(), children.end());
nodes->erase(nodes->find(id));
delete virus;
}
};
v_id stem_id;
boost::shared_ptr<Node> stem_node; //smart pointer pokazujacy na stem_node
typedef std::pair<v_id,boost::weak_ptr<Node> > map_entry;
public:
std::map<v_id, boost::weak_ptr<Node> > nodes; //mapa wierzcholkow (trzeba trzymac weak pointery, w readme wiecej)
VirusGenealogy() = delete;
// Tworzy nowa genealogie.
// Tworzy takze wezel wirusa macierzystego o identyfikatorze stem_id.
VirusGenealogy(v_id const &new_stem_id):
stem_id(new_stem_id),
stem_node(new Node(new_stem_id, &nodes))
{
stem_node->ja = boost::weak_ptr<Node>(stem_node);
stem_node->iterator_do_mnie = nodes.insert(map_entry(new_stem_id,boost::weak_ptr<Node> (stem_node))).first;
}
~VirusGenealogy()
{
stem_node.reset();
}
// Podaje identyfikator wirusa macierzystego.
v_id get_stem_id() const
{
return stem_id;
}
// Sprawdza, czy wirus o podanym identyfikatorze istnieje.
bool exists(v_id const &id) const
{
return (nodes.find(id) != nodes.end());
}
// Zwraca liste identyfikatorow bezposrednich nastepnikow wirusa
// o podanym identyfikatorze.
// Zglasza wyjatek VirusNotFound, jesli dany wirus nie istnieje.
std::vector<v_id> get_children(v_id const &id) const
{
if (!exists(id))
throw VirusNotFound();
std::vector<v_id> result ((nodes.find(id))->second.lock()-> children.size());
int i = 0;
//Przechodzimy po secie dzieci i dodajemy do wektora dzieci
for (boost::shared_ptr<Node> child : (nodes.find(id))->second.lock()-> children)
result[i++] = (child -> id);
return result;
}
// Zwraca liste identyfikatorow bezposrednich poprzednikow wirusa
// o podanym identyfikatorze.
// Zglasza wyjatek VirusNotFound, jesli dany wirus nie istnieje.
std::vector<v_id> get_parents(v_id const &id) const
{
if (!exists(id))
throw VirusNotFound();
std::vector<v_id> result ((nodes.find(id))->second.lock() -> parents.size());
//Przechodzimy po secie rodzicow i dodajemy do wektora rodzicow
int i = 0;
for (boost::weak_ptr<Node> parent : (nodes.find(id))->second.lock() -> parents) {
result[i++] = parent.lock() -> id;
}
return result;
}
// Zwraca referencje do obiektu reprezentujacego wirus o podanym
// identyfikatorze.
// Zglasza wyjatek VirusNotFound, jesli zadany wirus nie istnieje.
Virus& operator[](v_id const &id) const
{
if (!exists(id))
throw VirusNotFound();
return *(nodes.find(id)->second.lock() -> virus);
}
// Tworzy wezel reprezentujacy nowy wirus o identyfikatorze id
// powstaly z wirusow o podanym identyfikatorze parent_id lub
// podanych identyfikatorach parent_ids.
// Zglasza wyjatek VirusAlreadyCreated, jesli wirus o identyfikatorze
// id juz istnieje.
// Zglasza wyjatek VirusNotFound, jesli ktorys z wyspecyfikowanych
// poprzednikow nie istnieje.
void create(v_id const &id, v_id const &parent_id)
{
if (exists(id))
throw VirusAlreadyCreated();
if (!exists(parent_id))
throw VirusNotFound();
//wsadzamy do mapy wierzcholkow
boost::shared_ptr<Node> newNode(new Node(id, &nodes));
nodes.insert(map_entry(id, boost::weak_ptr<Node>(newNode)));
boost::weak_ptr<Node> createdNode= nodes.find(id)->second;
boost::weak_ptr<Node> parentNode= nodes.find(parent_id)->second;
//dodajemy rodzica do listy rodzicow nowego wierzcholka
createdNode.lock() -> parents.insert(boost::weak_ptr<Node>(parentNode));
//dodajemy dziecko do listy dzieci rodzica
parentNode.lock() -> children.insert(boost::shared_ptr<Node>(createdNode));
}
void create(v_id const &id, std::vector<v_id> const &parent_ids)
{
if (exists(id))
throw VirusAlreadyCreated();
for (v_id i : parent_ids)
if (!exists(i))
throw VirusNotFound();
//dodajemy do mapy wierzcholkow
boost::shared_ptr<Node> newNode(new Node(id, &nodes));
nodes.insert(map_entry(id, boost::weak_ptr<Node>(newNode)));
//uaktualniamy listy rodzicow i dzieci
boost::weak_ptr<Node> createdNode= nodes.find(id)->second;
for (v_id i : parent_ids)
{
boost::weak_ptr<Node> parentNode= nodes.find(i)->second;
//dodajemy rodzica do listy rodzicow nowego wierzcholka
createdNode.lock() -> parents.insert(boost::weak_ptr<Node>(parentNode));
//dodajemy dziecko do listy dzieci rodzica
parentNode.lock() -> children.insert(boost::shared_ptr<Node>(createdNode));
}
}
// Dodaje nowa krawedz w grafie genealogii.
// Zglasza wyjatek VirusNotFound, jesli ktorys z podanych wirusow nie istnieje.
void connect(v_id const &child_id, v_id const &parent_id)
{
if (!exists(child_id) || !exists(parent_id))
throw VirusNotFound();
boost::weak_ptr<Node> childNode= nodes.find(child_id)->second;
boost::weak_ptr<Node> parentNode= nodes.find(parent_id)->second;
//dodajemy rodzica do listy rodzicow nowego wierzcholka
childNode.lock() -> parents.insert(boost::weak_ptr<Node>(parentNode));
//dodajemy dziecko do listy dzieci rodzica
parentNode.lock() -> children.insert(boost::shared_ptr<Node>(childNode));
}
// Usuwa wirus o podanym identyfikatorze.
// Zglasza wyjatek VirusNotFound, jesli zadany wirus nie istnieje.
// Zglasza wyjatek TriedToRemoveStemVirus przy probie usuniecia wirusa macierzystego.
void remove(v_id const &id)
{
if (!exists(id))
throw VirusNotFound();
if (id == stem_id)
throw TriedToRemoveStemVirus();
boost::weak_ptr<Node> removedNode= nodes.find(id)->second;
//usuwamy wskaznik do usuwanego wierzcholka z listy dzieci u rodzica
//(powiazania z dziecmi sie usuna w destruktorze)
for (boost::weak_ptr<Node> parent : (removedNode.lock() -> parents))
{
parent.lock() -> children.erase(boost::shared_ptr<Node>(removedNode));
}
}
};
#endif