Skip to content

Commit 11be5c6

Browse files
authored
adding few more algorithms
,
1 parent c321ffd commit 11be5c6

File tree

8 files changed

+600
-80
lines changed

8 files changed

+600
-80
lines changed

src/bgaMain.cpp

+45-8
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@
44
// modify it under the terms as GNU General Public License.
55
///////////////////////////////////////////////////////////////////
66
//
7-
// basic Graph Algorithms.cpp : This file contains the 'main' function. Program execution begins and ends there.
7+
// basic Graph Algorithms
8+
// This file contains the 'main' function to start the execution
9+
// with a basic text user interface for all algorithms.
810
//
911

10-
#include "graph.h"
12+
#include "scc.h"
1113
#include "dfs.h"
1214
#include "mst.h"
1315
#include "shortestPath.h"
@@ -51,17 +53,32 @@ int main(int argc, char** argv)
5153
{
5254
cout << " help\n";
5355
cout << " print\n";
56+
cout << " transpose\n";
57+
cout << " scc [<node>]\n";
5458
cout << " search <root_node>\n"; // dfs search tree
5559
cout << " sort \n"; // levelize or topological sort
5660
cout << " mst [prim|kruskal]\n"; // minimal spanning tree
57-
cout << " path <root_node>\n"; // Shortest Path from single source to all vertices
61+
cout << " path <start_node> [<end_node>]\n"; // Path from source to one or all vertices
5862
cout << " quit\n";
5963
}
6064
else if (choice == "print")
6165
{
6266
graph->print();
6367
cout << "\n";
6468
}
69+
else if (choice == "transpose")
70+
{
71+
transpose reverse(false);
72+
const basicGraph::bGraph* new_graph = reverse.build(graph);
73+
new_graph->print();
74+
delete new_graph;
75+
}
76+
else if (choice == "scc")
77+
{
78+
SCC::kosaraju sccBuilder(graph);
79+
sccBuilder.build();
80+
sccBuilder.print();
81+
}
6582
else if (choice == "search")
6683
{
6784
if (tokens.size() < 2) {
@@ -110,15 +127,34 @@ int main(int argc, char** argv)
110127
cerr << "Error: supply search node and try again.\n";
111128
continue;
112129
}
113-
string node = tokens[1];
114-
const basicGraph::bNode* src = graph->findNode(node);
115-
if (!src) {
116-
cerr << "Error: node " << node << "not found in the graph.\n";
130+
string node1 = tokens[1];
131+
string node2 = tokens.size() > 2 ? tokens[2] : "" ;
132+
const basicGraph::bNode* src = graph->findNode(node1);
133+
if (!src)
134+
{
135+
cerr << "Error: node " << node1 << "not found in the graph.\n";
136+
continue;
117137
}
118-
else {
138+
const basicGraph::bNode* dst = node2.length() ? graph->findNode(node2) : nullptr;
139+
if (node2.size() && !dst)
140+
{
141+
cerr << "Error: node " << node2 << "not found in the graph.\n";
142+
cerr << " will use single source path algorithm.\n";
143+
}
144+
145+
if ( dst == nullptr )
146+
{
147+
// path to all nodes from source
119148
short_paths::dijkstra single_source_path(src, graph);
120149
single_source_path.build();
121150
single_source_path.print();
151+
}
152+
else
153+
{
154+
// a_star search for source and destination.
155+
short_paths::aStar src_dst_path(src, graph);
156+
src_dst_path.build(dst);
157+
src_dst_path.print(dst);
122158
}
123159
}
124160
else if (choice == "quit" || choice == "exit")
@@ -132,5 +168,6 @@ int main(int argc, char** argv)
132168
}
133169
}
134170

171+
delete graph;
135172
return 0;
136173
}

src/dfs.h

+10-11
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,7 @@
1616

1717
class DFS {
1818
private:
19-
typedef enum { NOT_VISITED = 1, VISITING = 2, VISITED = 3 } NODE_MARKS;
20-
map<const basicGraph::bNode*, NODE_MARKS> nodeMarks_;
19+
map<const basicGraph::bNode*, basicGraph::NODE_MARKS> nodeMarks_;
2120
basicGraph::bGraph* graph_;
2221

2322
string tabs(unsigned int level) {
@@ -30,47 +29,47 @@ class DFS {
3029
set<const basicGraph::bNode*, basicGraph::nodeCompare>::iterator niter = graph_->nodeBegin();
3130
for (; niter != graph_->nodeEnd(); niter++) {
3231
const basicGraph::bNode* node = *niter;
33-
DFS::nodeMarks_[node] = NOT_VISITED;
32+
DFS::nodeMarks_[node] = basicGraph::NOT_VISITED;
3433
}
3534
return;
3635
}
3736

3837
void search_int(const basicGraph::bNode* src, unsigned int level = 0)
3938
{
4039
cout << tabs(level++) << src->name() << " visiting" << endl;
41-
DFS::nodeMarks_[src] = VISITING;
40+
DFS::nodeMarks_[src] = basicGraph::VISITING;
4241

4342
set<const basicGraph::bEdge*, basicGraph::edgeCompare>::iterator niter = src->edgeBegin();
4443
for (; niter != src->edgeEnd(); niter++) {
4544
const basicGraph::bNode* nextNode = (*niter)->otherNode(src);
46-
if (DFS::nodeMarks_[nextNode] == DFS::NOT_VISITED)
45+
if (DFS::nodeMarks_[nextNode] == basicGraph::NOT_VISITED)
4746
search_int(nextNode);
4847
}
4948

50-
DFS::nodeMarks_[src] = VISITED;
49+
DFS::nodeMarks_[src] = basicGraph::VISITED;
5150
cout << tabs(level--) << src->name() << " visited." << endl;
5251
}
5352

5453
void ts_visit(const basicGraph::bNode* src, vector<vector<const basicGraph::bNode*>>& container, unsigned int level=0)
5554
{
56-
if (DFS::nodeMarks_[src] == DFS::VISITED)
55+
if (DFS::nodeMarks_[src] == basicGraph::VISITED)
5756
return;
5857

59-
if (DFS::nodeMarks_[src] == DFS::VISITING)
58+
if (DFS::nodeMarks_[src] == basicGraph::VISITING)
6059
{
6160
cerr << "Error: cycle deteceted at node " << src->name() << ". Topological sorting abandoned.\n";
6261
return;
6362
}
6463

65-
DFS::nodeMarks_[src] = DFS::VISITING;
64+
DFS::nodeMarks_[src] = basicGraph::VISITING;
6665

6766
set<const basicGraph::bEdge*, basicGraph::edgeCompare>::iterator niter = src->edgeBegin();
6867
for (; niter != src->edgeEnd(); niter++) {
6968
const basicGraph::bNode* nextNode = (*niter)->otherNode(src);
7069
ts_visit(nextNode, container, level+1);
7170
}
7271

73-
DFS::nodeMarks_[src] = DFS::VISITED;
72+
DFS::nodeMarks_[src] = basicGraph::VISITED;
7473
container[level].push_back(src);
7574

7675
return;
@@ -115,7 +114,7 @@ class DFS {
115114
for (; niter != graph_->nodeEnd(); niter++)
116115
{
117116
const basicGraph::bNode* src = *niter;
118-
if (DFS::nodeMarks_[src] != VISITED)
117+
if (DFS::nodeMarks_[src] != basicGraph::VISITED)
119118
ts_visit(src, levelized_container);
120119
}
121120

src/graph.cpp

+38-11
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,33 @@ void basicGraph::tokenizeLine(char* line, std::vector<std::string> &tokens)
4242
}
4343
}
4444

45+
basicGraph::bGraph::bGraph(const basicGraph::bGraph& other_graph)
46+
{
47+
isDirected_ = other_graph.directed();
48+
set<const basicGraph::bEdge*, basicGraph::edgeCompare>::iterator eiter;
49+
for (eiter = other_graph.edgeBegin(); eiter != other_graph.edgeEnd(); eiter++)
50+
{
51+
size_t wt = (*eiter)->hasWeight() ?
52+
dynamic_cast<const bWeightedEdge*>(*eiter)->weight() :
53+
basicGraph::bEdge::INVALID_WEIGHT;
54+
addNodesAndEdge((*eiter)->n1()->name(), (*eiter)->n2()->name(), wt);
55+
}
56+
return;
57+
}
58+
59+
void basicGraph::bGraph::addNodesAndEdge(string n1, string n2, size_t weight)
60+
{
61+
basicGraph::bNode* node1 = addNode(n1);
62+
basicGraph::bNode* node2 = addNode(n2);
63+
64+
const basicGraph::bEdge* edge = addEdge(node1, node2, weight);
65+
node1->addEdge(edge);
66+
if (!directed())
67+
node2->addEdge(edge);
68+
69+
return;
70+
}
71+
4572
void
4673
basicGraph::bGraph::print() const
4774
{
@@ -71,7 +98,7 @@ basicGraph::bGraph *basicGraph::bGraph::readBasicGraph(string filename)
7198
vector<string> tokens;
7299
tokenizeLine(line, tokens);
73100

74-
if (tokens.size() == 0 || tokens[0] == "#") {
101+
if (tokens.size() == 0 || tokens[0][0] == '#') {
75102
continue;
76103
}
77104
if (tokens.size() < 2)
@@ -87,18 +114,18 @@ basicGraph::bGraph *basicGraph::bGraph::readBasicGraph(string filename)
87114
else if (tokens[1] == "directed")
88115
new_graph->setDirected(true);
89116
else
90-
cerr << "invalid keyword after \'graph\' : " << tokens[1];
117+
cerr << "Error: invalid keyword after \'graph\' : " << tokens[1];
91118
}
92119
else {
93-
basicGraph::bNode* node1 = new_graph->addNode(tokens[0]);
94-
basicGraph::bNode* node2 = new_graph->addNode(tokens[1]);
95-
size_t weight = tokens.size() > 2 ?
96-
stol(tokens[2]) : basicGraph::bEdge::INVALID_WEIGHT;
97-
98-
const basicGraph::bEdge* edge = new_graph->addEdge(node1, node2, weight);
99-
node1->addEdge(edge);
100-
if (!new_graph->directed())
101-
node2->addEdge(edge);
120+
size_t weight = basicGraph::bEdge::INVALID_WEIGHT;
121+
if (tokens.size() > 2)
122+
{
123+
weight = stol(tokens[2]);
124+
if (weight < 0)
125+
cerr << "Warning: negative weight for the edge " << line << ".\n";
126+
}
127+
128+
new_graph->addNodesAndEdge(tokens[0], tokens[1], weight);
102129
}
103130
}
104131
buf.close();

src/graph.h

+10
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
using namespace std;
1919

2020
namespace basicGraph {
21+
typedef enum { NOT_VISITED = 1, VISITING = 2, VISITED = 3 } NODE_MARKS;
2122
class bNode;
2223
class bEdge;
2324

@@ -46,6 +47,7 @@ namespace basicGraph {
4647
edgelist_.insert(e);
4748
return true;
4849
}
50+
void clearEdgeList() { edgelist_.clear(); }
4951
set<const bEdge*, edgeCompare>::iterator edgeBegin() const { return edgelist_.begin(); }
5052
set<const bEdge*, edgeCompare>::iterator edgeEnd() const { return edgelist_.end(); }
5153
};
@@ -73,6 +75,12 @@ namespace basicGraph {
7375
const bNode* n1() const { return n1_; }
7476
const bNode* n2() const { return n2_; }
7577
virtual bool hasWeight() const {return false; }
78+
void swap_nodes() // used to compute transpose of graph
79+
{
80+
const bNode* tmp = n1_;
81+
n1_ = n2_;
82+
n2_ = tmp;
83+
}
7684
const bNode* otherNode(const bNode* n) const
7785
{
7886
if (n1_ == n)
@@ -115,6 +123,7 @@ namespace basicGraph {
115123
set<const bEdge*, edgeCompare> edgeset_;
116124
public:
117125
bGraph(bool directed=false) : isDirected_(directed) {}
126+
bGraph(const bGraph& other);
118127
void setDirected(bool directed) { isDirected_ = directed; }
119128
bool directed() const { return isDirected_; }
120129
const bNode* findNode(string name) {
@@ -158,6 +167,7 @@ namespace basicGraph {
158167
}
159168
return e;
160169
}
170+
void addNodesAndEdge(string, string, size_t);
161171
size_t nNodes() const { return nodeset_.size(); }
162172
size_t nEdges() const { return edgeset_.size(); }
163173

src/heap.h

+34
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,9 @@ class Heap : public std::vector<T> {
5656
Heap() {}
5757
void push(const T& element);
5858
bool pop(T&);
59+
bool erase(T&);
5960
bool exists(T&);
61+
bool index(T&, size_t&);
6062
inline size_t parent_index(size_t i) { return (i - 1) >> 1; }
6163
inline size_t left_index(size_t i) { return (i << 1) + 1; }
6264
inline size_t right_index(size_t i) { return (i << 1) + 2; }
@@ -125,6 +127,38 @@ Heap<T, COMPARE>::pop(T& popped) {
125127
return true;
126128
}
127129

130+
template<typename T, class COMPARE>
131+
bool
132+
Heap<T, COMPARE>::index(T& element, size_t& idx) {
133+
134+
for (size_t i = 0; i < this->size(); i++)
135+
{
136+
if ((*this)[i] == element)
137+
{
138+
idx = i;
139+
return true;
140+
}
141+
}
142+
return false;
143+
144+
}
145+
146+
template<typename T, class COMPARE>
147+
bool
148+
Heap<T, COMPARE>::erase(T& element) {
149+
if (!this->size()) return false;
150+
151+
size_t idx;
152+
if (index(element, idx))
153+
{
154+
(*this)[idx] = (*this)[this->size() - 1];
155+
((std::vector<T>*)this)->pop_back();
156+
heapify_down(idx);
157+
return true;
158+
}
159+
return false;
160+
}
161+
128162
template<typename T, class COMPARE>
129163
bool
130164
Heap<T, COMPARE>::exists(T& element) {

0 commit comments

Comments
 (0)