Skip to content

Commit c621526

Browse files
authored
Merge pull request #35 from Debashis08/release
Release
2 parents 6d44527 + 3ba353b commit c621526

10 files changed

+419
-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: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# pragma once
2+
3+
#include<map>
4+
#include<vector>
5+
#include<set>
6+
using namespace std;
7+
8+
namespace MinimumSpanningTreePrimAlgorithm
9+
{
10+
class Node
11+
{
12+
public:
13+
int data;
14+
Node* parent;
15+
int key;
16+
bool isInOperationalSet;
17+
Node(int data);
18+
};
19+
20+
class CompareNodeKey
21+
{
22+
public:
23+
bool operator()(const Node* nodeU, const Node* nodeV) const
24+
{
25+
return nodeU->key < nodeV->key;
26+
}
27+
};
28+
29+
class Graph
30+
{
31+
private:
32+
map<Node*, vector<pair<Node*, int>>> _adjlist;
33+
map<int, Node*> _nodeMap;
34+
vector<pair<pair<int, int>, int>> _minimumSpanningTree;
35+
multiset<Node*, CompareNodeKey> _operationalSet;
36+
Node* MakeOrFindNode(int data);
37+
public:
38+
void PushUndirectedEdge(int valueU, int valueV, int weight);
39+
void FindMinimumSpanningTreePrimAlgorithm();
40+
vector<pair<pair<int, int>, int>> GetMinimumSpanningTree();
41+
};
42+
}

README.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
## Data Structures and Algorithms
2+
3+
This repository contains a collection of **data structures and algorithms** implemented in **C++**. It is designed to provide efficient solutions to common algorithmic problems while adhering to clean coding practices and modular design.
4+
5+
### Features
6+
7+
- **Data Structures and Algorithms:** Implementations of data structures and algorithms based on the concepts from the book Introduction to Algorithms by Cormen, Leiserson, Rivest, and Stein (CLRS).
8+
- **Modular Design:** Code is organized into manageable modules for better readability and reusability.
9+
- **Testing:**
10+
- Built with **CMake** as the build system for ease of compilation and dependency management.
11+
- **Google Test** framework is integrated for comprehensive unit testing to ensure code correctness.
12+
13+
### Folder Structure
14+
15+
```plain text
16+
datastructures-algorithms
17+
├── Headers # Header Files
18+
├── SourceCodes # Implementation of the solutions
19+
├── Tests # Unit tests for implemented solutions
20+
└── CMakeLists.txt # CMake configuration file
21+
```
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
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+
85+
void Graph::FindMinimumSpanningTreeKruskalAlgorithm()
86+
{
87+
for (auto& iterator : this->_nodeMap)
88+
{
89+
this->MakeSet(iterator.second);
90+
}
91+
92+
sort(this->_edgeList.begin(), this->_edgeList.end(), [](Edge* edgeX, Edge* edgeY) { return edgeX->weight < edgeY->weight; });
93+
94+
for (auto& edge : this->_edgeList)
95+
{
96+
if (this->FindSet(edge->nodeU) != this->FindSet(edge->nodeV))
97+
{
98+
this->Union(edge->nodeU, edge->nodeV);
99+
this->_minimumSpanningTree.push_back({ {edge->nodeU->data, edge->nodeV->data}, edge->weight });
100+
}
101+
}
102+
}
103+
104+
vector<pair<pair<int, int>, int>> Graph::GetMinimumSpanningTree()
105+
{
106+
return this->_minimumSpanningTree;
107+
}
108+
}
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
#include "../Headers/0003_Graph/0008_MinimumSpanningTreePrimAlgorithm.h"
2+
#include<climits>
3+
using namespace std;
4+
5+
6+
namespace MinimumSpanningTreePrimAlgorithm
7+
{
8+
Node::Node(int data)
9+
{
10+
this->data = data;
11+
this->parent = nullptr;
12+
this->key = INT_MAX;
13+
this->isInOperationalSet = false;
14+
}
15+
16+
// Graph Private Member Methods
17+
Node* Graph::MakeOrFindNode(int data)
18+
{
19+
Node* node = nullptr;
20+
if (this->_nodeMap.find(data) == this->_nodeMap.end())
21+
{
22+
node = new Node(data);
23+
this->_nodeMap[data] = node;
24+
}
25+
else
26+
{
27+
node = this->_nodeMap[data];
28+
}
29+
return node;
30+
}
31+
32+
// Graph Public Member Methods
33+
void Graph::PushUndirectedEdge(int dataU, int dataV, int weight)
34+
{
35+
Node* nodeU = this->MakeOrFindNode(dataU);
36+
Node* nodeV = this->MakeOrFindNode(dataV);
37+
38+
this->_adjlist[nodeU].push_back({nodeV, weight});
39+
this->_adjlist[nodeV].push_back({nodeU, weight});
40+
}
41+
42+
void Graph::FindMinimumSpanningTreePrimAlgorithm()
43+
{
44+
Node* root = this->_nodeMap.begin()->second;
45+
46+
root->key = 0;
47+
for (auto& iterator : this->_nodeMap)
48+
{
49+
iterator.second->isInOperationalSet = true;
50+
this->_operationalSet.insert(iterator.second);
51+
}
52+
53+
while (!this->_operationalSet.empty())
54+
{
55+
Node* nodeU = *(this->_operationalSet.begin());
56+
this->_operationalSet.erase(nodeU);
57+
nodeU->isInOperationalSet = false;
58+
59+
for (auto& iterator : this->_adjlist[nodeU])
60+
{
61+
Node* nodeV = iterator.first;
62+
int weight = iterator.second;
63+
64+
if (nodeV->isInOperationalSet && weight < nodeV->key)
65+
{
66+
this->_operationalSet.erase(nodeV);
67+
nodeV->key = weight;
68+
nodeV->parent = nodeU;
69+
this->_operationalSet.insert(nodeV);
70+
71+
}
72+
}
73+
74+
if (nodeU->parent != nullptr)
75+
{
76+
this->_minimumSpanningTree.push_back({ {nodeU->parent->data, nodeU->data}, nodeU->key });
77+
}
78+
}
79+
}
80+
81+
vector<pair<pair<int, int>, int>> Graph::GetMinimumSpanningTree()
82+
{
83+
return this->_minimumSpanningTree;
84+
}
85+
}

SourceCodes/0003_Graph/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ set(0003GRAPH_SOURCES
66
0004_StronglyConnectedComponents.cc
77
0005_HamiltonianPathAndCycle.cc
88
0006_EulerianPathAndCircuit.cc
9+
0007_MinimumSpanningTreeKruskalAlgorithm.cc
10+
0008_MinimumSpanningTreePrimAlgorithm.cc
11+
912
)
1013

1114
# Create a library target

Tests/0000_CommonUtilities/UnitTestHelper.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,4 +136,26 @@ 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+
if (pairA.second == pairB.second)
154+
{
155+
return pairA.first.first < pairB.first.first;
156+
}
157+
return pairA.second < pairB.second;
158+
});
159+
return data;
160+
}
139161
};
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+
}

0 commit comments

Comments
 (0)