I have written an iterative implementation of depth first search (DFS) algorithm in C++. It produces correct visiting order as output. Algorithm goes like that:
- Initiate visited[] array with false values.
- Push first vertex into stack.
- Pop element from stack and assign it to variable v.
- If v was not visited (visited[v] == false), print v and set it as visited.
- Push every not visited neighbors of v into stack (biggest value first).
- Repeat 3-5 until stack is empty.
The problem I have is to determine proper Stack s size in DFSIteratively method of GraphUtilities class. My teacher stated it has to be stored as array. I am able to calculate it's size using (n * n - 3 * n + 2) / 2 equation, where n is vertex set count, assuming no visited vertex is ever pushed into stack and full graph was provided (most dense graph; pessimistic case).
Can stack size be determined for factual graph, which most likely will not be a full graph? Or, better yet, is there a way to push every vertex into stack only once? I know recursive implementations solves this limitation, as well as using dynamic data struct as stack, but my project assumes using array (educational purposes, that's what I was told).
#include <iostream>
#include <stdexcept>
#include <list>
#include <sstream>
#include <fstream>
#include <cstdlib>
using namespace std;
template <typename T> class Stack
{
private:
int ptr;
T *stackArray;
int stackSize;
public:
Stack(int n)
{
ptr = -1;
stackSize = n;
stackArray = new T[stackSize];
}
~Stack()
{
delete[] stackArray;
}
void push(T x)
{
if(ptr + 1 == stackSize)
throw length_error("Cannot push.");
stackArray[++ptr] = x;
}
T top()
{
if(ptr == -1)
throw length_error("Cannot pop.");
return stackArray[ptr];
}
T pop()
{
T temp = top();
ptr--;
return temp;
}
bool isEmpty()
{
if(ptr == -1)
return true;
return false;
}
};
class Graph
{
private:
int numberOfVertices;
list<int> *adjacencyList;
public:
Graph(int n)
{
numberOfVertices = n;
adjacencyList = new list<int>[numberOfVertices];
}
int getNumberOfVertices()
{
return numberOfVertices;
}
list<int>* getAdjacencyList(int v)
{
return &adjacencyList[v];
}
list<int>* getAdjacencyList()
{
return adjacencyList;
}
~Graph()
{
delete[] adjacencyList;
}
void addEdge(int v1, int v2)
{
adjacencyList[v1].push_back(v2);
}
};
class GraphUtilities
{
private:
bool *visited;
stringstream visitingOrder;
public:
void DFSIteratively(Graph &g, int v)
{
int n = g.getNumberOfVertices();
list<int> *adjacencyList = g.getAdjacencyList();
visited = new bool[n];
Stack<int> *s;
// Determine size of stack.
if(n == 1)
s = new Stack<int>(1);
else
s = new Stack<int>( (n*n - 3*n + 2)/2 );
for(int i = 0; i < n; i++)
visited[i] = false;
s -> push(v);
while(!(s -> isEmpty()))
{
v = s -> pop();
if(!visited[v])
{
visitingOrder << v << " ";
visited[v] = true;
for(list<int>::reverse_iterator i = adjacencyList[v].rbegin(); i != adjacencyList[v].rend(); ++i)
if(!(visited[*i]))
s -> push(*i);
}
}
cout << visitingOrder.str() << endl;
visitingOrder.clear();
delete[] visited;
delete s;
}
};
int main()
{
Graph graph(6);
GraphUtilities utilities;
graph.addEdge(0, 1);
graph.addEdge(0, 2);
graph.addEdge(0, 4);
graph.addEdge(1, 0);
graph.addEdge(1, 5);
graph.addEdge(2, 0);
graph.addEdge(2, 5);
graph.addEdge(3, 5);
graph.addEdge(4, 0);
graph.addEdge(5, 1);
graph.addEdge(5, 2);
graph.addEdge(5, 3);
utilities.DFSIteratively(graph, 4);
return 0;
}
My graph (paint quality): http://i.imgur.com/pkGKNFo.jpg
Output:
4 0 1 3 5 2