Skip to content

Commit d5c4538

Browse files
authored
Merge pull request #26 from Debashis08/feature-graph-implementation
Feature graph implementation
2 parents a9c428b + 5f95bc2 commit d5c4538

File tree

10 files changed

+239
-26
lines changed

10 files changed

+239
-26
lines changed
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#pragma once
2+
3+
#include<map>
4+
#include<unordered_set>
5+
#include<vector>
6+
using namespace std;
7+
8+
class HamiltonianNode
9+
{
10+
public:
11+
int data;
12+
bool isVisited;
13+
HamiltonianNode(int value);
14+
};
15+
16+
class HamiltonianGraph
17+
{
18+
private:
19+
bool _isHamiltonianCyclePresent;
20+
bool _isHamiltonianPathPresent;
21+
int _visitedNodeCount;
22+
HamiltonianNode* _startingNode;
23+
map<HamiltonianNode*, unordered_set<HamiltonianNode*>> _adjlist;
24+
map<int, HamiltonianNode*> _nodeMap;
25+
vector<int> _hamiltonianPath;
26+
HamiltonianNode* MakeOrFindNode(int value);
27+
bool IsSafe(HamiltonianNode* nodeU, HamiltonianNode* nodeV);
28+
bool HamiltonianCycleAndPathUtil(HamiltonianNode* node);
29+
30+
public:
31+
void PushUndirectedEdge(int valueU, int valueV);
32+
void PushSingleNode(int valueU);
33+
void FindHamiltonianCycleAndPath();
34+
bool IsHamiltonianCyclePresent();
35+
bool IsHamiltonianPathPresent();
36+
vector<int> GetHamiltonianPath();
37+
};
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
#include "../Headers/0003_Graph/0005_HamiltonianPathAndCycle.h"
2+
3+
using namespace std;
4+
5+
HamiltonianNode::HamiltonianNode(int value)
6+
{
7+
this->data = value;
8+
this->isVisited = false;
9+
}
10+
11+
// HamiltonianGraph Private Member Methods
12+
HamiltonianNode* HamiltonianGraph::MakeOrFindNode(int value)
13+
{
14+
HamiltonianNode* node = nullptr;
15+
if (this->_nodeMap.find(value) == this->_nodeMap.end())
16+
{
17+
node = new HamiltonianNode(value);
18+
this->_nodeMap[value] = node;
19+
}
20+
else
21+
{
22+
node = this->_nodeMap[value];
23+
}
24+
return node;
25+
}
26+
27+
bool HamiltonianGraph::IsSafe(HamiltonianNode* nodeU, HamiltonianNode* nodeV)
28+
{
29+
if (this->_adjlist[nodeU].find(nodeV) == this->_adjlist[nodeU].end())
30+
{
31+
return false;
32+
}
33+
if (nodeV->isVisited == true)
34+
{
35+
return false;
36+
}
37+
return true;
38+
}
39+
40+
bool HamiltonianGraph::HamiltonianCycleAndPathUtil(HamiltonianNode* nodeU)
41+
{
42+
if (this->_visitedNodeCount == this->_nodeMap.size())
43+
{
44+
if (this->_adjlist[nodeU].find(this->_startingNode) != this->_adjlist[nodeU].end())
45+
{
46+
this->_isHamiltonianCyclePresent = true;
47+
this->_isHamiltonianPathPresent = true;
48+
return true;
49+
}
50+
this->_isHamiltonianPathPresent = true;
51+
return false;
52+
}
53+
for (auto& nodeV : this->_adjlist[nodeU])
54+
{
55+
if (this->IsSafe(nodeU, nodeV))
56+
{
57+
this->_hamiltonianPath.push_back(nodeV->data);
58+
nodeV->isVisited = true;
59+
this->_visitedNodeCount++;
60+
if (this->HamiltonianCycleAndPathUtil(nodeV))
61+
{
62+
return true;
63+
}
64+
this->_visitedNodeCount--;
65+
nodeV->isVisited = false;
66+
this->_hamiltonianPath.pop_back();
67+
}
68+
}
69+
return false;
70+
}
71+
72+
// HamiltonianGraph Public Member Methods
73+
void HamiltonianGraph::PushUndirectedEdge(int valueU, int valueV)
74+
{
75+
HamiltonianNode* nodeU = this->MakeOrFindNode(valueU);
76+
HamiltonianNode* nodeV = this->MakeOrFindNode(valueV);
77+
78+
this->_adjlist[nodeU].insert(nodeV);
79+
this->_adjlist[nodeV].insert(nodeU);
80+
}
81+
82+
void HamiltonianGraph::PushSingleNode(int valueU)
83+
{
84+
HamiltonianNode* nodeU = this->MakeOrFindNode(valueU);
85+
}
86+
87+
void HamiltonianGraph::FindHamiltonianCycleAndPath()
88+
{
89+
this->_isHamiltonianCyclePresent = false;
90+
this->_isHamiltonianPathPresent = false;
91+
this->_hamiltonianPath = {};
92+
this->_startingNode = this->_nodeMap[0];
93+
this->_hamiltonianPath.push_back(this->_startingNode->data);
94+
this->_startingNode->isVisited = true;
95+
this->_visitedNodeCount = 1;
96+
this->HamiltonianCycleAndPathUtil(this->_startingNode);
97+
}
98+
99+
bool HamiltonianGraph::IsHamiltonianCyclePresent()
100+
{
101+
return this->_isHamiltonianCyclePresent;
102+
}
103+
104+
bool HamiltonianGraph::IsHamiltonianPathPresent()
105+
{
106+
return this->_isHamiltonianPathPresent;
107+
}
108+
109+
vector<int> HamiltonianGraph::GetHamiltonianPath()
110+
{
111+
return this->_hamiltonianPath;
112+
}

SourceCodes/0003_Graph/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ set(0003GRAPH_SOURCES
44
0002_DepthFirstSearch.cc
55
0003_TopologicalSort.cc
66
0004_StronglyConnectedComponents.cc
7+
0005_HamiltonianPathAndCycle.cc
78
)
89

910
# Create a library target

Tests/0000_CommonUtilities/UnitTestHelper.h

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ class UnitTestHelper
1010
{
1111
public:
1212
template<typename T>
13-
string VerifyVectorResult(vector<T> vector)
13+
string SerializeVectorToString(vector<T> vector)
1414
{
1515
string result = "";
1616
for (auto& iterator : vector)
@@ -22,7 +22,7 @@ class UnitTestHelper
2222
}
2323

2424
template<typename T>
25-
string VerifyVectorResult(vector<pair<T,T>> vector)
25+
string SerializeVectorToString(vector<pair<T,T>> vector)
2626
{
2727
string result = "";
2828
for (auto& iterator : vector)
@@ -38,7 +38,7 @@ class UnitTestHelper
3838
}
3939

4040
template<typename T>
41-
string VerifyVectorResult(vector<pair<T, pair<T, T>>> vector)
41+
string SerializeVectorToString(vector<pair<T, pair<T, T>>> vector)
4242
{
4343
string result = "";
4444
for (auto& iterator : vector)
@@ -54,7 +54,7 @@ class UnitTestHelper
5454
}
5555

5656
template<typename T>
57-
string VerifyVectorResult(vector<vector<T>> vector)
57+
string SerializeVectorToString(vector<vector<T>> vector)
5858
{
5959
string result = "";
6060
for (auto& iterator : vector)
@@ -107,4 +107,33 @@ class UnitTestHelper
107107

108108
return data;
109109
}
110+
111+
template<typename T>
112+
bool NormalizeCyclesAnCompare(vector<T> data1, vector<T> data2)
113+
{
114+
if (data1.size() != data2.size())
115+
{
116+
return false;
117+
}
118+
119+
// Normalized rotation of cycle 1
120+
vector<T> normalizedCycle1(data1);
121+
auto minIterator1 = min_element(normalizedCycle1.begin(), normalizedCycle1.end());
122+
rotate(normalizedCycle1.begin(), minIterator1, normalizedCycle1.end());
123+
124+
// Normalized rotation of cycle 2
125+
vector<T> normalizedCycle2(data2);
126+
auto minIterator2 = min_element(normalizedCycle2.begin(), normalizedCycle2.end());
127+
rotate(normalizedCycle2.begin(), minIterator2, normalizedCycle2.end());
128+
129+
// Check clock wise
130+
if (normalizedCycle1 == normalizedCycle2)
131+
{
132+
return true;
133+
}
134+
135+
// Check counter clock wise
136+
reverse(normalizedCycle2.begin() + 1, normalizedCycle2.end());
137+
return (normalizedCycle1 == normalizedCycle2);
138+
}
110139
};

Tests/0002_Tree/0001_BinarySearchTreeTest.cc

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ namespace BinarySearchTreeTest
1515
bst.InsertNode(60);
1616

1717

18-
string actualResult = unitTestHelper.VerifyVectorResult(bst.GetRecursiveInorderTravesalResult());
18+
string actualResult = unitTestHelper.SerializeVectorToString(bst.GetRecursiveInorderTravesalResult());
1919
string expectedResult = "30 50 60";
2020

2121
EXPECT_EQ(actualResult, expectedResult);
@@ -28,7 +28,7 @@ namespace BinarySearchTreeTest
2828
bst.InsertNode(30);
2929
bst.InsertNode(60);
3030

31-
string actualResult = unitTestHelper.VerifyVectorResult(bst.GetRecursivePreorderTravesalResult());
31+
string actualResult = unitTestHelper.SerializeVectorToString(bst.GetRecursivePreorderTravesalResult());
3232
string expectedResult = "50 30 60";
3333

3434
EXPECT_EQ(actualResult, expectedResult);
@@ -41,7 +41,7 @@ namespace BinarySearchTreeTest
4141
bst.InsertNode(30);
4242
bst.InsertNode(60);
4343

44-
string actualResult = unitTestHelper.VerifyVectorResult(bst.GetRecursivePostorderTravesalResult());
44+
string actualResult = unitTestHelper.SerializeVectorToString(bst.GetRecursivePostorderTravesalResult());
4545
string expectedResult = "30 60 50";
4646

4747
EXPECT_EQ(actualResult, expectedResult);
@@ -55,7 +55,7 @@ namespace BinarySearchTreeTest
5555
bst.InsertNode(60);
5656

5757

58-
string actualResult = unitTestHelper.VerifyVectorResult(bst.GetMorrisInorderTraversalResult());
58+
string actualResult = unitTestHelper.SerializeVectorToString(bst.GetMorrisInorderTraversalResult());
5959
string expectedResult = "30 50 60";
6060

6161
EXPECT_EQ(actualResult, expectedResult);
@@ -69,7 +69,7 @@ namespace BinarySearchTreeTest
6969
bst.InsertNode(60);
7070

7171

72-
string actualResult = unitTestHelper.VerifyVectorResult(bst.GetMorrisPreorderTraversalResult());
72+
string actualResult = unitTestHelper.SerializeVectorToString(bst.GetMorrisPreorderTraversalResult());
7373
string expectedResult = "50 30 60";
7474

7575
EXPECT_EQ(actualResult, expectedResult);
@@ -83,7 +83,7 @@ namespace BinarySearchTreeTest
8383
bst.InsertNode(60);
8484

8585

86-
string actualResult = unitTestHelper.VerifyVectorResult(bst.GetMorrisPostorderTraversalResult());
86+
string actualResult = unitTestHelper.SerializeVectorToString(bst.GetMorrisPostorderTraversalResult());
8787
string expectedResult = "30 60 50";
8888

8989
EXPECT_EQ(actualResult, expectedResult);

Tests/0003_Graph/0001_BreadthFirstSearchTest.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ namespace BreadthFirstSearchTest
2525

2626
graph.BFS(1);
2727

28-
string actualResult = unitTestHelper.VerifyVectorResult(graph.ShowBFSResult());
28+
string actualResult = unitTestHelper.SerializeVectorToString(graph.ShowBFSResult());
2929
string expectedResult = "1(0) 2(1) 3(1) 4(2) 5(2) 6(2) 7(3) 8(3)";
3030
EXPECT_EQ(actualResult, expectedResult);
3131
}
@@ -38,7 +38,7 @@ namespace BreadthFirstSearchTest
3838

3939
graph.BFS(1);
4040

41-
string actualResult = unitTestHelper.VerifyVectorResult(graph.ShowBFSResult());
41+
string actualResult = unitTestHelper.SerializeVectorToString(graph.ShowBFSResult());
4242
string expectedResult = "1(0) 2(1)";
4343
EXPECT_EQ(actualResult, expectedResult);
4444
}

Tests/0003_Graph/0002_DepthFirstSearchTest.cc

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ namespace DepthFirstSearchTest
2121

2222
graph.DFS();
2323

24-
string actualResult = unitTestHelper.VerifyVectorResult(graph.ShowDFSResult());
24+
string actualResult = unitTestHelper.SerializeVectorToString(graph.ShowDFSResult());
2525
string expectedResult = "1(1,8) 2(2,7) 3(9,12) 4(4,5) 5(3,6) 6(10,11)";
2626
EXPECT_EQ(actualResult, expectedResult);
2727
}
@@ -35,7 +35,7 @@ namespace DepthFirstSearchTest
3535

3636
graph.DFS();
3737

38-
string actualResult = unitTestHelper.VerifyVectorResult(graph.ShowDFSResult());
38+
string actualResult = unitTestHelper.SerializeVectorToString(graph.ShowDFSResult());
3939
string expectedResult = "1(1,2)";
4040
EXPECT_EQ(actualResult, expectedResult);
4141
}
@@ -49,7 +49,7 @@ namespace DepthFirstSearchTest
4949

5050
graph.DFS();
5151

52-
string actualResult = unitTestHelper.VerifyVectorResult(graph.ShowDFSResult());
52+
string actualResult = unitTestHelper.SerializeVectorToString(graph.ShowDFSResult());
5353
string expectedResult = "1(1,4) 2(2,3) 3(5,8) 4(6,7)";
5454
EXPECT_EQ(actualResult, expectedResult);
5555
}
@@ -64,7 +64,7 @@ namespace DepthFirstSearchTest
6464

6565
graph.DFS();
6666

67-
string actualResult = unitTestHelper.VerifyVectorResult(graph.ShowDFSResult());
67+
string actualResult = unitTestHelper.SerializeVectorToString(graph.ShowDFSResult());
6868
string expectedResult = "1(1,6) 2(2,5) 3(3,4)";
6969
EXPECT_EQ(actualResult, expectedResult);
7070
}
@@ -92,7 +92,7 @@ namespace DepthFirstSearchTest
9292

9393
graph.DFS();
9494

95-
string actualResult = unitTestHelper.VerifyVectorResult(graph.ShowDFSResult());
95+
string actualResult = unitTestHelper.SerializeVectorToString(graph.ShowDFSResult());
9696
string expectedResult = "1(1,32) 2(2,29) 3(30,31) 4(3,28) 5(4,27) 6(5,26) 7(6,25) 8(7,24) 9(8,23) 10(9,22) 11(10,21) 12(11,20) 13(12,19) 14(13,18) 15(14,17) 16(15,16)";
9797
EXPECT_EQ(actualResult, expectedResult);
9898
}
@@ -108,7 +108,7 @@ namespace DepthFirstSearchTest
108108

109109
graph.DFS();
110110

111-
string actualResult = unitTestHelper.VerifyVectorResult(graph.ShowDFSResult());
111+
string actualResult = unitTestHelper.SerializeVectorToString(graph.ShowDFSResult());
112112
string expectedResult = "1(1,2) 2(3,4) 3(5,6)";
113113
EXPECT_EQ(actualResult, expectedResult);
114114
}
@@ -125,7 +125,7 @@ namespace DepthFirstSearchTest
125125

126126
graph.DFS();
127127

128-
string actualResult = unitTestHelper.VerifyVectorResult(graph.ShowDFSResult());
128+
string actualResult = unitTestHelper.SerializeVectorToString(graph.ShowDFSResult());
129129
string expectedResult = "1(1,8) 2(2,7) 3(3,4) 4(5,6)";
130130
EXPECT_EQ(actualResult, expectedResult);
131131
}
@@ -150,7 +150,7 @@ namespace DepthFirstSearchTest
150150

151151
graph.DFS();
152152

153-
string actualResult = unitTestHelper.VerifyVectorResult(graph.ShowDFSResult());
153+
string actualResult = unitTestHelper.SerializeVectorToString(graph.ShowDFSResult());
154154
string expectedResult = "1(1,8) 2(2,7) 3(3,6) 4(4,5)";
155155
EXPECT_EQ(actualResult, expectedResult);
156156
}
@@ -169,7 +169,7 @@ namespace DepthFirstSearchTest
169169

170170
graph.DFS();
171171

172-
string actualResult = unitTestHelper.VerifyVectorResult(graph.ShowDFSResult());
172+
string actualResult = unitTestHelper.SerializeVectorToString(graph.ShowDFSResult());
173173
string expectedResult = "1(1,6) 2(2,5) 3(3,4)";
174174
EXPECT_EQ(actualResult, expectedResult);
175175
}

0 commit comments

Comments
 (0)