0
votes

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:

  1. Initiate visited[] array with false values.
  2. Push first vertex into stack.
  3. Pop element from stack and assign it to variable v.
  4. If v was not visited (visited[v] == false), print v and set it as visited.
  5. Push every not visited neighbors of v into stack (biggest value first).
  6. 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

1
Isn't this more of math question than a programming question? Have you tried math.stackexchange.com - 4386427
It might be. Thanks, I will certainly check it. - Harmala

1 Answers

0
votes

Probably you might be happier if you'll use additional addedToStack flag array of size n next to your visited array. So if you'll add a vertex to stack it will not be visited but added to stack. There is no need in adding it to the stack again. Check addedToStack flag each time you want to add a vertex to the stack. Eventually every vertex will occur in the stack not more than once and the stack size will be n at most.