Skip to content

Commit 069b26b

Browse files
committed
feature: eulerian path logic added
1 parent 3104206 commit 069b26b

File tree

3 files changed

+219
-0
lines changed

3 files changed

+219
-0
lines changed
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,39 @@
11
#pragma once
22

3+
#include<map>
4+
#include<vector>
5+
#include<unordered_set>
6+
using namespace std;
7+
8+
namespace EulerianPathAndCircuit
9+
{
10+
class Node
11+
{
12+
public:
13+
int data;
14+
int degree;
15+
bool visited;
16+
Node(int value);
17+
};
18+
19+
class Graph
20+
{
21+
private:
22+
bool _isEulerianPathPresent;
23+
bool _isEulerianCircuitPresent;
24+
map<Node*, unordered_set<Node*>> _adjlist;
25+
map<int, Node*> _nodeMap;
26+
vector<int> _eulerianPath;
27+
Node* MakeOrFindNode(int value);
28+
void DepthFirstSearch(Node* node);
29+
bool IsConnected();
30+
31+
public:
32+
void PushUndirectedEdge(int valueU, int valueV);
33+
void PushSingleNode(int valueU);
34+
void FindEulerianPathAndCircuit();
35+
bool IsEulerianPathPresent();
36+
bool IsEulerianCircuitPresent();
37+
vector<int> GetEulerianPath();
38+
};
39+
}
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
#include "../Headers/0003_Graph/0006_EulerianPathAndCircuit.h"
2+
using namespace std;
3+
4+
namespace EulerianPathAndCircuit
5+
{
6+
Node::Node(int value)
7+
{
8+
this->data = value;
9+
this->visited = false;
10+
this->degree = 0;
11+
}
12+
13+
// Graph Private Member Methods
14+
Node* Graph::MakeOrFindNode(int value)
15+
{
16+
Node* node = nullptr;
17+
if (this->_nodeMap.find(value) == this->_nodeMap.end())
18+
{
19+
node = new Node(value);
20+
this->_nodeMap[value] = node;
21+
}
22+
else
23+
{
24+
node = this->_nodeMap[value];
25+
}
26+
return node;
27+
}
28+
29+
// Graph Public Member Methods
30+
void Graph::PushUndirectedEdge(int valueU, int valueV)
31+
{
32+
Node* nodeU = this->MakeOrFindNode(valueU);
33+
Node* nodeV = this->MakeOrFindNode(valueV);
34+
35+
this->_adjlist[nodeU].insert(nodeV);
36+
nodeU->degree++;
37+
this->_adjlist[nodeV].insert(nodeU);
38+
nodeV->degree++;
39+
}
40+
41+
void Graph::DepthFirstSearch(Node* nodeU)
42+
{
43+
nodeU->visited = true;
44+
this->_eulerianPath.push_back(nodeU->data);
45+
for (auto& nodeV : this->_adjlist[nodeU])
46+
{
47+
if (nodeV->visited == false)
48+
{
49+
this->DepthFirstSearch(nodeV);
50+
}
51+
}
52+
}
53+
54+
bool Graph::IsConnected()
55+
{
56+
// Step-1 : Make the visited property of all nodes as false. It is already done in constructor.
57+
58+
// Step-2 : Find a node which do not have 0 degree.
59+
Node* node = nullptr;
60+
for (auto& iterator : this->_nodeMap)
61+
{
62+
if (iterator.second->degree != 0)
63+
{
64+
node = iterator.second;
65+
break;
66+
}
67+
}
68+
69+
// Step-3 : If node is null, it means G.E is null, so G is connected, else call DFS to traverse the graph G.
70+
if (node == nullptr)
71+
{
72+
return true;
73+
}
74+
75+
this->DepthFirstSearch(node);
76+
77+
// Step-4 : Checking if all the non-zero degree vertexes have been visited or not.
78+
for (auto& iterator : this->_nodeMap)
79+
{
80+
if (iterator.second->visited == false && iterator.second->degree != 0)
81+
{
82+
return false;
83+
}
84+
}
85+
return true;
86+
}
87+
88+
void Graph::PushSingleNode(int valueU)
89+
{
90+
Node* nodeU = this->MakeOrFindNode(valueU);
91+
}
92+
93+
void Graph::FindEulerianPathAndCircuit()
94+
{
95+
// If the graph is not connected then graph G is Not-Eulerian.
96+
if (this->IsConnected() == false)
97+
{
98+
this->_isEulerianPathPresent = false;
99+
this->_isEulerianCircuitPresent = false;
100+
return;
101+
}
102+
103+
int oddDegreeVertexCount = 0;
104+
for (auto& iterator : this->_nodeMap)
105+
{
106+
if (iterator.second->degree & 1)
107+
{
108+
oddDegreeVertexCount++;
109+
}
110+
}
111+
112+
// Check-1 : When no vertex with odd degree is present, then graph G is Eulerian.
113+
if (oddDegreeVertexCount == 0)
114+
{
115+
this->_isEulerianPathPresent = true;
116+
this->_isEulerianCircuitPresent = true;
117+
return;
118+
}
119+
120+
// Check-2 : When 2 vertex have odd degree, then graph G is Semi-Eulerian.
121+
if (oddDegreeVertexCount == 2)
122+
{
123+
this->_isEulerianPathPresent = true;
124+
this->_isEulerianCircuitPresent = false;
125+
return;
126+
}
127+
128+
// Check-3 : When more than 2 vertexes have odd degree, then graph G is Not Eulerian.
129+
if (oddDegreeVertexCount > 2)
130+
{
131+
this->_isEulerianPathPresent = false;
132+
this->_isEulerianCircuitPresent = false;
133+
return;
134+
}
135+
}
136+
137+
bool Graph::IsEulerianPathPresent()
138+
{
139+
return this->_isEulerianPathPresent;
140+
}
141+
142+
bool Graph::IsEulerianCircuitPresent()
143+
{
144+
return this->_isEulerianCircuitPresent;
145+
}
146+
147+
// Not properly implemented
148+
vector<int> Graph::GetEulerianPath()
149+
{
150+
return this->_eulerianPath;
151+
}
152+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#include<gtest/gtest.h>
2+
#include "../Headers/0003_Graph/0006_EulerianPathAndCircuit.h"
3+
#include "../0000_CommonUtilities/UnitTestHelper.h"
4+
5+
namespace EulerianPathAndCircuit
6+
{
7+
UnitTestHelper unitTestHelper;
8+
9+
TEST(EulerianPathAndCycle, Test1)
10+
{
11+
Graph graph;
12+
13+
graph.PushUndirectedEdge(1, 0);
14+
graph.PushUndirectedEdge(0, 2);
15+
graph.PushUndirectedEdge(2, 1);
16+
graph.PushUndirectedEdge(0, 3);
17+
graph.PushUndirectedEdge(3, 4);
18+
graph.PushUndirectedEdge(4, 0);
19+
20+
graph.FindEulerianPathAndCircuit();
21+
22+
bool isEulerianPathPresent = graph.IsEulerianPathPresent();
23+
bool isEulerianCircuitPresent = graph.IsEulerianCircuitPresent();
24+
25+
vector<int> eulerianPath = graph.GetEulerianPath();
26+
27+
ASSERT_TRUE(isEulerianPathPresent);
28+
ASSERT_TRUE(isEulerianCircuitPresent);
29+
}
30+
}

0 commit comments

Comments
 (0)