Skip to content

Commit 8b20ebd

Browse files
authored
Merge pull request #31 from Debashis08/feature-graph-implementation
Feature graph implementation
2 parents 3bacc51 + 09bd22f commit 8b20ebd

File tree

6 files changed

+219
-0
lines changed

6 files changed

+219
-0
lines changed
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#pragma once
2+
3+
#include<map>
4+
#include<vector>
5+
#include<list>
6+
using namespace std;
7+
8+
namespace MinimumSpanningTreeKruskalAlgorithm
9+
{
10+
class Node
11+
{
12+
public:
13+
int data;
14+
Node* parent;
15+
int rank;
16+
Node(int data);
17+
};
18+
19+
class Edge
20+
{
21+
public:
22+
Node* nodeU;
23+
Node* nodeV;
24+
int weight;
25+
Edge(Node* nodeU, Node* nodeV, int weight);
26+
};
27+
28+
class Graph
29+
{
30+
private:
31+
map<Node*, vector<Node*>> _adjlist;
32+
map<int, Node*> _nodeMap;
33+
vector<Edge*> _edgeList;
34+
vector<pair<pair<int, int>, int>> _minimumSpanningTree;
35+
Node* MakeOrFindNode(int data);
36+
void MakeSet(Node* node);
37+
void Union(Node* nodeU, Node* nodeV);
38+
void Link(Node* nodeU, Node* nodeV);
39+
Node* FindSet(Node* node);
40+
41+
public:
42+
void PushUndirectedEdge(int valueU, int valueV, int weight);
43+
void FindMinimumSpanningTreeKruskalAlgorithm();
44+
vector<pair<pair<int, int>, int>> GetMinimumSpanningTree();
45+
};
46+
}
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
#include "../Headers/0003_Graph/0007_MinimumSpanningTreeKruskalAlgorithm.h"
2+
#include<climits>
3+
#include<algorithm>
4+
using namespace std;
5+
6+
namespace MinimumSpanningTreeKruskalAlgorithm
7+
{
8+
Node::Node(int data)
9+
{
10+
this->data = data;
11+
this->parent = nullptr;
12+
this->rank = INT_MAX;
13+
}
14+
15+
Edge::Edge(Node* nodeU, Node* nodeV, int weight)
16+
{
17+
this->nodeU = nodeU;
18+
this->nodeV = nodeV;
19+
this->weight = weight;
20+
}
21+
22+
// Graph Private Member Methods
23+
Node* Graph::MakeOrFindNode(int data)
24+
{
25+
Node* node = nullptr;
26+
if (this->_nodeMap.find(data) == this->_nodeMap.end())
27+
{
28+
node = new Node(data);
29+
this->_nodeMap[data] = node;
30+
}
31+
else
32+
{
33+
node = this->_nodeMap[data];
34+
}
35+
return node;
36+
}
37+
38+
void Graph::MakeSet(Node* node)
39+
{
40+
node->parent = node;
41+
node->rank = 0;
42+
}
43+
44+
void Graph::Union(Node* nodeU, Node* nodeV)
45+
{
46+
this->Link(this->FindSet(nodeU), this->FindSet(nodeV));
47+
}
48+
49+
void Graph::Link(Node* nodeU, Node* nodeV)
50+
{
51+
if (nodeV->rank > nodeU->rank)
52+
{
53+
nodeU->parent = nodeV;
54+
}
55+
else
56+
{
57+
nodeV->parent = nodeU;
58+
if (nodeU->rank == nodeV->rank)
59+
{
60+
nodeU->rank += 1;
61+
}
62+
}
63+
}
64+
65+
Node* Graph::FindSet(Node* node)
66+
{
67+
if (node != node->parent)
68+
{
69+
node->parent = this->FindSet(node->parent);
70+
}
71+
return node->parent;
72+
}
73+
74+
// Graph Public Member Methods
75+
void Graph::PushUndirectedEdge(int dataU, int dataV, int weight)
76+
{
77+
Node* nodeU = this->MakeOrFindNode(dataU);
78+
Node* nodeV = this->MakeOrFindNode(dataV);
79+
80+
this->_adjlist[nodeU].push_back(nodeV);
81+
this->_adjlist[nodeV].push_back(nodeU);
82+
this->_edgeList.push_back(new Edge(nodeU, nodeV, weight));
83+
}
84+
void Graph::FindMinimumSpanningTreeKruskalAlgorithm()
85+
{
86+
for (auto iterator : this->_nodeMap)
87+
{
88+
this->MakeSet(iterator.second);
89+
}
90+
91+
sort(this->_edgeList.begin(), this->_edgeList.end(), [](Edge* edgeX, Edge* edgeY) { return edgeX->weight < edgeY->weight; });
92+
93+
for (auto edge : this->_edgeList)
94+
{
95+
if (this->FindSet(edge->nodeU) != this->FindSet(edge->nodeV))
96+
{
97+
this->Union(edge->nodeU, edge->nodeV);
98+
this->_minimumSpanningTree.push_back({ {edge->nodeU->data, edge->nodeV->data}, edge->weight });
99+
}
100+
}
101+
}
102+
103+
vector<pair<pair<int, int>, int>> Graph::GetMinimumSpanningTree()
104+
{
105+
return this->_minimumSpanningTree;
106+
}
107+
}

SourceCodes/0003_Graph/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ set(0003GRAPH_SOURCES
66
0004_StronglyConnectedComponents.cc
77
0005_HamiltonianPathAndCycle.cc
88
0006_EulerianPathAndCircuit.cc
9+
0007_MinimumSpanningTreeKruskalAlgorithm.cc
10+
911
)
1012

1113
# Create a library target

Tests/0000_CommonUtilities/UnitTestHelper.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,4 +136,22 @@ class UnitTestHelper
136136
reverse(normalizedCycle2.begin() + 1, normalizedCycle2.end());
137137
return (normalizedCycle1 == normalizedCycle2);
138138
}
139+
140+
template<typename T>
141+
vector<pair<pair<T, T>, T>> SortVectorOfPair(vector<pair<pair<T, T>, T>> data)
142+
{
143+
for (auto& iterator : data)
144+
{
145+
if (iterator.first.first > iterator.first.second)
146+
{
147+
swap(iterator.first.first, iterator.first.second);
148+
}
149+
}
150+
151+
sort(data.begin(), data.end(), [](const pair<pair<T, T>, T>& pairA, const pair<pair<T, T>, T>& pairB)
152+
{
153+
return pairA.second < pairB.second;
154+
});
155+
return data;
156+
}
139157
};
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
#include<gtest/gtest.h>
2+
#include "../Headers/0003_Graph/0007_MinimumSpanningTreeKruskalAlgorithm.h"
3+
#include "../0000_CommonUtilities/UnitTestHelper.h"
4+
5+
namespace MinimumSpanningTreeKruskalAlgorithm
6+
{
7+
UnitTestHelper unitTestHelper;
8+
9+
TEST(MST, Kruskal)
10+
{
11+
Graph graph;
12+
13+
graph.PushUndirectedEdge(1, 2, 4);
14+
graph.PushUndirectedEdge(1, 8, 8);
15+
graph.PushUndirectedEdge(2, 8, 11);
16+
graph.PushUndirectedEdge(2, 3, 8);
17+
graph.PushUndirectedEdge(3, 4, 7);
18+
graph.PushUndirectedEdge(3, 9, 2);
19+
graph.PushUndirectedEdge(3, 6, 4);
20+
graph.PushUndirectedEdge(4, 5, 9);
21+
graph.PushUndirectedEdge(4, 6, 14);
22+
graph.PushUndirectedEdge(5, 6, 10);
23+
graph.PushUndirectedEdge(6, 7, 2);
24+
graph.PushUndirectedEdge(7, 8, 1);
25+
graph.PushUndirectedEdge(7, 9, 6);
26+
graph.PushUndirectedEdge(8, 9, 7);
27+
28+
graph.FindMinimumSpanningTreeKruskalAlgorithm();
29+
30+
vector<pair<pair<int,int>, int>> actualMST = graph.GetMinimumSpanningTree();
31+
vector<pair<pair<int, int>, int>> expectedMST =
32+
{
33+
{{7, 8}, 1},
34+
{{3, 9}, 2},
35+
{{6, 7}, 2},
36+
{{2, 1}, 4},
37+
{{3, 6}, 4},
38+
{{3, 4}, 7},
39+
{{8, 1}, 8},
40+
{{4, 5}, 9}
41+
};
42+
43+
ASSERT_EQ(unitTestHelper.SortVectorOfPair(actualMST), unitTestHelper.SortVectorOfPair(expectedMST));
44+
}
45+
}

Tests/0003_Graph/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ add_executable(
1818
0004_StronglyConnectedComponentsTest.cc
1919
0005_HamiltonianPathAndCycleTest.cc
2020
0006_EulerianPathAndCircuitTest.cc
21+
0007_MinimumSpanningTreeKruskalAlgorithmTest.cc
2122
)
2223

2324
target_link_libraries(

0 commit comments

Comments
 (0)