Skip to content

Commit acfd3fe

Browse files
committed
core: Hierholzer algorithm added
1 parent 069b26b commit acfd3fe

File tree

2 files changed

+86
-21
lines changed

2 files changed

+86
-21
lines changed

Headers/0003_Graph/0006_EulerianPathAndCircuit.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
#include<map>
44
#include<vector>
5-
#include<unordered_set>
5+
#include<list>
66
using namespace std;
77

88
namespace EulerianPathAndCircuit
@@ -12,6 +12,8 @@ namespace EulerianPathAndCircuit
1212
public:
1313
int data;
1414
int degree;
15+
int inDegree;
16+
int outDegree;
1517
bool visited;
1618
Node(int value);
1719
};
@@ -21,19 +23,21 @@ namespace EulerianPathAndCircuit
2123
private:
2224
bool _isEulerianPathPresent;
2325
bool _isEulerianCircuitPresent;
24-
map<Node*, unordered_set<Node*>> _adjlist;
26+
map<Node*, list<Node*>> _adjlist;
2527
map<int, Node*> _nodeMap;
2628
vector<int> _eulerianPath;
2729
Node* MakeOrFindNode(int value);
2830
void DepthFirstSearch(Node* node);
2931
bool IsConnected();
32+
void EulerianPathHierholzerAlgorithm(Node* startingNode);
3033

3134
public:
3235
void PushUndirectedEdge(int valueU, int valueV);
36+
void PushDirectedEdge(int valueU, int valueV);
3337
void PushSingleNode(int valueU);
3438
void FindEulerianPathAndCircuit();
3539
bool IsEulerianPathPresent();
3640
bool IsEulerianCircuitPresent();
37-
vector<int> GetEulerianPath();
41+
vector<int> UndirectedGraphGetEulerianPath();
3842
};
3943
}

SourceCodes/0003_Graph/0006_EulerianPathAndCircuit.cc

Lines changed: 79 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
11
#include "../Headers/0003_Graph/0006_EulerianPathAndCircuit.h"
2+
#include<stack>
3+
#include<algorithm>
24
using namespace std;
35

46
namespace EulerianPathAndCircuit
57
{
68
Node::Node(int value)
79
{
810
this->data = value;
9-
this->visited = false;
1011
this->degree = 0;
12+
this->inDegree = 0;
13+
this->outDegree = 0;
14+
this->visited = false;
1115
}
1216

1317
// Graph Private Member Methods
@@ -26,18 +30,6 @@ namespace EulerianPathAndCircuit
2630
return node;
2731
}
2832

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-
4133
void Graph::DepthFirstSearch(Node* nodeU)
4234
{
4335
nodeU->visited = true;
@@ -74,7 +66,7 @@ namespace EulerianPathAndCircuit
7466

7567
this->DepthFirstSearch(node);
7668

77-
// Step-4 : Checking if all the non-zero degree vertexes have been visited or not.
69+
// Step-4 : Checking if all the non-zero degree vertices have been visited or not.
7870
for (auto& iterator : this->_nodeMap)
7971
{
8072
if (iterator.second->visited == false && iterator.second->degree != 0)
@@ -85,6 +77,50 @@ namespace EulerianPathAndCircuit
8577
return true;
8678
}
8779

80+
void Graph::EulerianPathHierholzerAlgorithm(Node* startingNode)
81+
{
82+
stack<Node*> currentPath;
83+
currentPath.push(startingNode);
84+
while (!currentPath.empty())
85+
{
86+
Node* currentNode = currentPath.top();
87+
if (!this->_adjlist[currentNode].empty())
88+
{
89+
Node* nextNode = this->_adjlist[currentNode].front();
90+
this->_adjlist[currentNode].pop_front();
91+
this->_adjlist[nextNode].remove(currentNode);
92+
currentPath.push(nextNode);
93+
}
94+
else
95+
{
96+
currentPath.pop();
97+
this->_eulerianPath.push_back(currentNode->data);
98+
}
99+
}
100+
}
101+
102+
// Graph Public Member Methods
103+
void Graph::PushUndirectedEdge(int valueU, int valueV)
104+
{
105+
Node* nodeU = this->MakeOrFindNode(valueU);
106+
Node* nodeV = this->MakeOrFindNode(valueV);
107+
108+
this->_adjlist[nodeU].push_back(nodeV);
109+
nodeU->degree++;
110+
this->_adjlist[nodeV].push_back(nodeU);
111+
nodeV->degree++;
112+
}
113+
114+
void Graph::PushDirectedEdge(int valueU, int valueV)
115+
{
116+
Node* nodeU = this->MakeOrFindNode(valueU);
117+
Node* nodeV = this->MakeOrFindNode(valueV);
118+
119+
this->_adjlist[nodeU].push_back(nodeV);
120+
nodeU->outDegree++;
121+
nodeV->inDegree++;
122+
}
123+
88124
void Graph::PushSingleNode(int valueU)
89125
{
90126
Node* nodeU = this->MakeOrFindNode(valueU);
@@ -117,15 +153,15 @@ namespace EulerianPathAndCircuit
117153
return;
118154
}
119155

120-
// Check-2 : When 2 vertex have odd degree, then graph G is Semi-Eulerian.
156+
// Check-2 : When 2 vertices have odd degree, then graph G is Semi-Eulerian.
121157
if (oddDegreeVertexCount == 2)
122158
{
123159
this->_isEulerianPathPresent = true;
124160
this->_isEulerianCircuitPresent = false;
125161
return;
126162
}
127163

128-
// Check-3 : When more than 2 vertexes have odd degree, then graph G is Not Eulerian.
164+
// Check-3 : When more than 2 vertices have odd degree, then graph G is Not Eulerian.
129165
if (oddDegreeVertexCount > 2)
130166
{
131167
this->_isEulerianPathPresent = false;
@@ -144,9 +180,34 @@ namespace EulerianPathAndCircuit
144180
return this->_isEulerianCircuitPresent;
145181
}
146182

147-
// Not properly implemented
148-
vector<int> Graph::GetEulerianPath()
183+
vector<int> Graph::UndirectedGraphGetEulerianPath()
149184
{
185+
// Case-3 : When more than 2 vertices have odd degree, then the graph G is not Eulerian.
186+
// No Eulerian Path is posible.
187+
if (this->_isEulerianPathPresent == false)
188+
{
189+
return {};
190+
}
191+
192+
// Now 2 cases remains.
193+
// Case-2 : When 2 vertices have odd degree. Choose any one of them.
194+
Node* node = nullptr;
195+
for (auto& iterator : this->_nodeMap)
196+
{
197+
if (iterator.second->degree & 1)
198+
{
199+
node = iterator.second;
200+
break;
201+
}
202+
}
203+
204+
// Case-1 : When no vertex with odd degree is present. Choose any vertex as starting point.
205+
if (node == nullptr)
206+
{
207+
node = this->_nodeMap[0];
208+
}
209+
this->EulerianPathHierholzerAlgorithm(node);
210+
reverse(this->_eulerianPath.begin(), this->_eulerianPath.end());
150211
return this->_eulerianPath;
151212
}
152213
}

0 commit comments

Comments
 (0)