Skip to content
This repository was archived by the owner on Nov 29, 2020. It is now read-only.

Commit 8f01c88

Browse files
committed
BFS.cpp
1 parent 3b2324a commit 8f01c88

File tree

6 files changed

+203
-42
lines changed

6 files changed

+203
-42
lines changed

BFS.cpp

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
//
2+
// algorithm - some algorithms in "Introduction to Algorithms", third edition
3+
// Copyright (C) 2018 lxylxy123456
4+
//
5+
// This program is free software: you can redistribute it and/or modify
6+
// it under the terms of the GNU Affero General Public License as
7+
// published by the Free Software Foundation, either version 3 of the
8+
// License, or (at your option) any later version.
9+
//
10+
// This program is distributed in the hope that it will be useful,
11+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
// GNU Affero General Public License for more details.
14+
//
15+
// You should have received a copy of the GNU Affero General Public License
16+
// along with this program. If not, see <https://www.gnu.org/licenses/>.
17+
//
18+
19+
#ifndef MAIN
20+
#define MAIN
21+
#define MAIN_BFS
22+
#endif
23+
24+
#ifndef FUNC_BFS
25+
#define FUNC_BFS
26+
27+
#include <cassert>
28+
#include "utils.h"
29+
30+
#include "Queue.cpp"
31+
#include "Graph.cpp"
32+
33+
const size_t INF = -1;
34+
35+
enum BFSColor { white, gray, black };
36+
37+
template <typename T>
38+
class BFSInfo {
39+
public:
40+
BFSInfo(): color(white), d(INF) {}
41+
BFSInfo(enum BFSColor c, size_t dist): color(c), d(dist) {}
42+
BFSInfo(enum BFSColor c, size_t dist, T p): color(c), d(dist), pi(p) {}
43+
enum BFSColor color;
44+
size_t d;
45+
T pi;
46+
};
47+
48+
template <typename GT, typename T>
49+
void BFS(GT& G, T s, umap<T, BFSInfo<T>>& ans) {
50+
for (auto i = G.V.begin(); i != G.V.end(); i++) {
51+
if (*i == s)
52+
ans[*i] = BFSInfo<T>(gray, 0);
53+
else
54+
ans[*i] = BFSInfo<T>();
55+
}
56+
Queue<T> Q(G.V.size());
57+
Q.Enqueue(s);
58+
while (!Q.Empty()) {
59+
T u = Q.Dequeue();
60+
for (auto i = G.edges_from(u); !i.end(); i++)
61+
if (ans[i.d()].color == white) {
62+
ans[i.d()].color = gray;
63+
ans[i.d()].d = ans[u].d + 1;
64+
ans[i.d()].pi = u;
65+
Q.Enqueue(i.d());
66+
}
67+
ans[u].color = black;
68+
}
69+
}
70+
71+
template <typename T>
72+
void PrintPath(T s, T v, umap<T, BFSInfo<T>> inf, std::vector<T>& ans) {
73+
if (v == s)
74+
ans.push_back(v);
75+
else if (inf[v].d != INF) {
76+
PrintPath(s, inf[v].pi, inf, ans);
77+
ans.push_back(v);
78+
}
79+
}
80+
#endif
81+
82+
#ifdef MAIN_BFS
83+
int main(int argc, char *argv[]) {
84+
const size_t v = get_argv(argc, argv, 1, 5);
85+
const size_t e = get_argv(argc, argv, 2, 10);
86+
const bool dir = get_argv(argc, argv, 3, 0);
87+
GraphAdjList<size_t> G(dir);
88+
random_graph(G, v, e);
89+
umap<size_t, BFSInfo<size_t>> inf;
90+
size_t s = 0;
91+
BFS(G, s, inf);
92+
auto f1 = [inf](size_t v) mutable {
93+
BFSInfo<size_t>& i = inf[v];
94+
std::cout << " [";
95+
switch (i.color) {
96+
case white:
97+
break;
98+
case black:
99+
std::cout << "color=black style=filled fontcolor=white ";
100+
break;
101+
case gray:
102+
std::cout << "color=gray style=filled ";
103+
break;
104+
}
105+
std::cout << "label=\"" << v << "\\n";
106+
if (i.d == 0)
107+
std::cout << "d = " << i.d;
108+
else if (i.d == INF)
109+
std::cout << "d = INF";
110+
else
111+
std::cout << "d = " << i.d << "; pi = " << i.pi;
112+
std::cout << "\"";
113+
std::cout << "]";
114+
return true;
115+
};
116+
auto f2 = [dir](Edge<size_t> e) {};
117+
graphviz(G, f1, f2);
118+
for (auto i = G.V.begin(); i != G.V.end(); i++) {
119+
std::vector<size_t> ans;
120+
PrintPath(s, *i, inf, ans);
121+
std::cout << *i << '\t';
122+
if (ans.size())
123+
output_integers(ans);
124+
else
125+
std::cout << "no path from " << s << " exists" << std::endl;
126+
}
127+
return 0;
128+
}
129+
#endif
130+

Graph.cpp

Lines changed: 50 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,10 @@
2626

2727
#include <unordered_set>
2828
#include <unordered_map>
29-
#include <iterator>
3029
#include "utils.h"
3130

32-
#define set typename std::unordered_set
33-
#define map typename std::unordered_map
31+
#define uset typename std::unordered_set
32+
#define umap typename std::unordered_map
3433

3534
template <typename T>
3635
class Edge {
@@ -49,7 +48,7 @@ class Edge {
4948
template <typename T>
5049
class EdgeIteratorAL1 {
5150
public:
52-
EdgeIteratorAL1(map<T, set<T>>& E, bool direction): dir(direction) {
51+
EdgeIteratorAL1(umap<T, uset<T>>& E, bool direction): dir(direction) {
5352
mbegin = E.begin();
5453
mend = E.end();
5554
sbegin = mbegin->second.begin();
@@ -83,14 +82,14 @@ class EdgeIteratorAL1 {
8382
T s() { return mbegin->first; }
8483
T d() { return *sbegin; }
8584
bool dir;
86-
map<T, set<T>>::iterator mbegin, mend;
87-
set<T>::iterator sbegin, send;
85+
umap<T, uset<T>>::iterator mbegin, mend;
86+
uset<T>::iterator sbegin, send;
8887
};
8988

9089
template <typename T>
9190
class EdgeIteratorAL2 {
9291
public:
93-
EdgeIteratorAL2(T ss, set<T>& E, bool direction): S(ss), dir(direction){
92+
EdgeIteratorAL2(T ss, uset<T>& E, bool direction): S(ss),dir(direction){
9493
sbegin = E.begin();
9594
send = E.end();
9695
}
@@ -108,13 +107,13 @@ class EdgeIteratorAL2 {
108107
T d() { return *sbegin; }
109108
T S;
110109
bool dir;
111-
set<T>::iterator sbegin, send;
110+
uset<T>::iterator sbegin, send;
112111
};
113112

114113
template <typename T>
115114
class EdgeIteratorAM1 {
116115
public:
117-
EdgeIteratorAM1(map<T, map<T, bool>>& E, bool direction) {
116+
EdgeIteratorAM1(umap<T, umap<T, bool>>& E, bool direction) {
118117
dir = direction;
119118
mbegin = E.begin();
120119
mend = E.end();
@@ -149,14 +148,14 @@ class EdgeIteratorAM1 {
149148
T s() { return mbegin->first; }
150149
T d() { return sbegin->first; }
151150
bool dir;
152-
map<T, map<T, bool>>::iterator mbegin, mend;
153-
map<T, bool>::iterator sbegin, send;
151+
umap<T, umap<T, bool>>::iterator mbegin, mend;
152+
umap<T, bool>::iterator sbegin, send;
154153
};
155154

156155
template <typename T>
157156
class EdgeIteratorAM2 {
158157
public:
159-
EdgeIteratorAM2(T ss, map<T, bool>& E, bool direction): S(ss) {
158+
EdgeIteratorAM2(T ss, umap<T, bool>& E, bool direction): S(ss) {
160159
dir = direction;
161160
sbegin = E.begin();
162161
send = E.end();
@@ -181,7 +180,7 @@ class EdgeIteratorAM2 {
181180
T d() { return sbegin->first; }
182181
T S;
183182
bool dir;
184-
map<T, bool>::iterator sbegin, send;
183+
umap<T, bool>::iterator sbegin, send;
185184
};
186185

187186
template <typename T>
@@ -194,11 +193,15 @@ class Graph {
194193
V.insert(u);
195194
return true;
196195
}
196+
void add_edge(Edge<T> e) {
197+
this->add_edge(e.s, e.d);
198+
}
197199
virtual void add_edge(T, T) = 0;
198200
virtual bool is_edge(T u, T v) = 0;
199201
virtual ~Graph() {}
202+
typedef T vertix_type;
200203
bool dir;
201-
set<T> V;
204+
uset<T> V;
202205
};
203206

204207
template <typename T>
@@ -222,7 +225,7 @@ class GraphAdjList: public Graph<T> {
222225
return EdgeIteratorAL2<T>(s, E[s], this->dir);
223226
}
224227
virtual ~GraphAdjList() {}
225-
map<T, set<T>> E;
228+
umap<T, uset<T>> E;
226229
};
227230

228231
template <typename T>
@@ -256,7 +259,7 @@ class GraphAdjMatrix: public Graph<T> {
256259
return EdgeIteratorAM2<T>(s, E[s], this->dir);
257260
}
258261
virtual ~GraphAdjMatrix() {}
259-
map<T, map<T, bool>> E;
262+
umap<T, umap<T, bool>> E;
260263
};
261264

262265
template <typename T>
@@ -269,44 +272,43 @@ void random_graph(Graph<T>& G, T v, T e) {
269272
G.add_edge(d[2 * i], d[2 * i + 1]);
270273
}
271274

272-
template <typename T>
273-
void graphviz(T& G) {
275+
template <typename T, typename F1, typename F2>
276+
void graphviz(T& G, F1 f1, F2 f2) {
274277
if (G.dir)
275278
std::cout << "digraph G {" << std::endl;
276279
else
277280
std::cout << "graph G {" << std::endl;
278281
std::cout << '\t';
279-
for (auto i = G.V.begin(); i != G.V.end(); i++)
280-
std::cout << *i << "; ";
282+
for (auto i = G.V.begin(); i != G.V.end(); i++) {
283+
std::cout << *i;
284+
if (f1(*i))
285+
std::cout << "; \n\t";
286+
else
287+
std::cout << "; ";
288+
}
281289
std::cout << std::endl;
282290
for (auto i = G.all_edges(); !i.end(); i++)
283-
if (G.dir || i.s() < i.d())
284-
std::cout << '\t' << *i << "; " << std::endl;
291+
if (G.dir || i.s() < i.d()) {
292+
std::cout << '\t' << *i;
293+
f2(*i);
294+
std::cout << "; " << std::endl;
295+
}
285296
std::cout << "}" << std::endl;
286297
}
298+
299+
template <typename T>
300+
void graphviz(T& G) {
301+
auto f1 = [](typename T::vertix_type v) { return false; };
302+
auto f2 = [](Edge<typename T::vertix_type>) {};
303+
graphviz(G, f1, f2);
304+
}
287305
#endif
288306

289307
#ifdef MAIN_Graph
290-
int main(int argc, char *argv[]) {
291-
const size_t v = get_argv(argc, argv, 1, 5);
292-
const size_t e = get_argv(argc, argv, 2, 10);
293-
for (size_t dir = 0; dir <= 1; dir++) {
294-
GraphAdjList<size_t> G(dir);
295-
random_graph(G, v, e);
296-
for (auto i = G.all_edges(); !i.end(); i++)
297-
std::cout << *i << std::endl;
298-
std::cout << std::endl;
299-
for (auto i = G.V.begin(); i != G.V.end(); i++) {
300-
std::cout << *i << std::endl;
301-
for (auto j = G.edges_from(*i); !j.end(); j++)
302-
std::cout << '\t' << *j << std::endl;
303-
}
304-
std::cout << std::endl;
305-
graphviz(G);
306-
std::cout << std::endl;
307-
}
308+
template <typename T>
309+
void graph_test(const size_t v, const size_t e) {
308310
for (size_t dir = 0; dir <= 1; dir++) {
309-
GraphAdjMatrix<size_t> G(dir);
311+
T G(dir);
310312
random_graph(G, v, e);
311313
for (auto i = G.all_edges(); !i.end(); i++)
312314
std::cout << *i << std::endl;
@@ -320,6 +322,13 @@ int main(int argc, char *argv[]) {
320322
graphviz(G);
321323
std::cout << std::endl;
322324
}
325+
}
326+
327+
int main(int argc, char *argv[]) {
328+
const size_t v = get_argv(argc, argv, 1, 5);
329+
const size_t e = get_argv(argc, argv, 2, 10);
330+
graph_test<GraphAdjList<size_t>>(v, e);
331+
graph_test<GraphAdjMatrix<size_t>>(v, e);
323332
return 0;
324333
}
325334
#endif

Queue.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ class Queue {
4646
head = 0;
4747
return ans;
4848
}
49+
bool Empty() {
50+
return head == tail;
51+
}
4952
~Queue() { delete [] data; }
5053
private:
5154
size_t head, tail, length;
@@ -59,6 +62,7 @@ int main(int argc, char *argv[]) {
5962
Queue<int> S(n);
6063
std::cout << "d: dequeue" << std::endl;
6164
std::cout << "e: enqueue" << std::endl;
65+
std::cout << "E: empty" << std::endl;
6266
std::cout << "q: quit" << std::endl;
6367
while (true) {
6468
char c; int x;
@@ -76,6 +80,9 @@ int main(int argc, char *argv[]) {
7680
case 'd':
7781
std::cout << S.Dequeue() << std::endl;
7882
break;
83+
case 'E':
84+
std::cout << std::boolalpha << S.Empty() << std::endl;
85+
break;
7986
case 'q':
8087
return 0;
8188
}

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,8 @@
144144
| 21 | DisjointSet.cpp | Union | 571 |
145145
| 21 | DisjointSet.cpp | Link | 571 |
146146
| 21 | DisjointSet.cpp | Find Set | 571 |
147+
| 22 | BFS.cpp | BFS | 595 |
148+
| 22 | BFS.cpp | Print Path | 601 |
147149

148150
# Supplementary Files
149151
* `utils.h`: Utils
@@ -152,3 +154,4 @@
152154
# Supplementary Programs
153155
* `include_check.py`: identifies unnecessary includes
154156
* `vEB_check.py`: compare results of `ProtovEB.cpp` and `vEB.cpp`
157+
* `dot.sh`: generate a graphviz graph from stdin

dot.sh

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
mkdir /tmp/.dot.sh/ 2> /dev/null
2+
3+
if [ $# == 0 ]; then
4+
A=`mktemp /tmp/.dot.sh/XXXXXXXX.dot`
5+
cat > $A
6+
else
7+
A=$1
8+
fi
9+
10+
B=`mktemp /tmp/.dot.sh/XXXXXXXX.png`
11+
dot $A -Tpng -o $B && gnome-open $B 2> /dev/null > /dev/null
12+

include_check.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
assert 'std::invalid_argument' in a
1919
elif j == 'map' :
2020
assert 'std::map' in a or 'std::pair' in a
21-
elif j in ['list', 'set'] :
21+
elif j in ['list', 'set', 'unordered_set', 'unordered_map'] :
2222
assert 'std::' + j in a
2323
else :
2424
assert(False)

0 commit comments

Comments
 (0)