在迭代深度优先搜索(DFS)算法中确定堆栈大小

时间:2015-12-19 03:30:31

标签: c++ stack iteration size depth-first-search

我在C ++中编写了深度优先搜索(DFS)算法的迭代实现。它产生正确的访问顺序作为输出。算法就是这样:

  1. 使用false值启动visited []数组。
  2. 将第一个顶点推入堆栈。
  3. 从堆栈弹出元素并将其分配给变量v。
  4. 如果未访问v(访问[v] == false),请打印v并将其设置为已访问。
  5. 将v的每个未访问过的邻居推入堆栈(最大值优先)。
  6. 重复3-5,直到堆栈为空。
  7. 我遇到的问题是在GraphUtilities类的DFSIteratively方法中确定正确的Stack大小。我的老师说它必须存储为数组。我能够使用(n * n - 3 * n + 2)/ 2等式计算它的大小,其中n是顶点集计数,假设没有被访问的顶点被推入堆栈并且提供了完整的图形(大多数密集图;悲观情况)。

    可以为实际图确定堆栈大小,这很可能不是完整的图形吗?或者,更好的是,有没有办法将每个顶点仅推入堆栈一次?我知道递归实现解决了这个限制,以及使用动态数据结构作为堆栈,但我的项目假设使用数组(教育目的,这就是我所说的)。

    #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;
    }
    

    我的图表(油漆质量):http://i.imgur.com/pkGKNFo.jpg

    输出:

      

    4 0 1 3 5 2

1 个答案:

答案 0 :(得分:0)

如果您在addedToStack数组旁边使用大小为n的其他visited标记数组,则可能会更高兴。因此,如果您要将一个顶点添加到堆栈,它将不会被访问但会添加到堆栈中。无需再次将其添加到堆栈中。每次要将顶点添加到堆栈时,请检查 addedToStack 标记。最终,每个顶点都会在堆栈中出现不超过一次,堆栈大小最多为 n