[英]Determining stack size in iterative depth first search (DFS) algorithm
I have written an iterative implementation of depth first search (DFS) algorithm in C++. 我用C ++编写了深度优先搜索(DFS)算法的迭代实现。 It produces correct visiting order as output. 它产生正确的访问顺序作为输出。 Algorithm goes like that: 算法是这样的:
The problem I have is to determine proper Stack s size in DFSIteratively method of GraphUtilities class. 我的问题是在GraphUtilities类的DFSIteratively方法中确定正确的Stack大小。 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). 我可以使用(n * n-3 * n + 2)/ 2等式计算它的大小,其中n是顶点集计数,假设没有访问过的顶点被压入堆栈并提供了全图(最密集的图;悲观的)案件)。
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 我的图表(画质): http : //i.imgur.com/pkGKNFo.jpg
Output: 输出:
4 0 1 3 5 2 4 0 1 3 5 2
Probably you might be happier if you'll use additional addedToStack
flag array of size n
next to your visited
array. 如果在visited
数组旁边使用大小为n
其他addedToStack
标志数组,可能会更快乐。 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. 每次要将顶点添加到堆栈时,请检查addedToStack标志。 Eventually every vertex will occur in the stack not more than once and the stack size will be n at most. 最终,每个顶点在堆栈中出现的次数不会超过一次,并且堆栈大小最多为n 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.