如何解决如何修复Skiena的dfs深度优先搜索实现c++中的无限循环
即使在 Steven Skiena 第二版的“算法设计手册”一书中的 Skiena dfs 实现中包含勘误表更改之后,我仍然遇到了无限循环,我想知道如何修复它。 原因似乎很明显,适用于任何无向图,这让我觉得可能是我做错了,但就是想不通。
取任何无向图(如果你有这本书,或者在 pg171 上的那个),假设有一条边 (1,6)。在邻接列表中,alist[6] 将有一个节点为 1,alist[1] 将有一个节点为 6。为顶点 = 1 启动 DFS(调用 dfs(1)),它首先发现 6 并设置 parent[6]= 1.递归调用 dfs(6) 然后想要发现 1 但 1 已经被发现。这首先导致 while 循环中的 if 条件变为 false
if (!discovered[y]) )
因此不会设置 parent[1]。
1 尚未处理且 parent[6] 为 1(即前一次迭代中设置的),因此 else if while 循环中的条件也是假的。
else if (((!processed[y]) && (parents[v] != y)) || (directed))
由于 else 条件 a 为假,我们没有将指针 p 重置为链表中的下一个节点,因此它进入了无限循环
while (p != nullptr)
所以基本上它在处理第一条边 (1,6) 和 (6,1) 时卡住了,这应该发生在任何无向图上。这个无限循环的修复是什么?或者我在这里做错了与skiena实施不同的事情?
这是重现无限循环的最小可编译和可运行代码,包括 main()
#include <iostream>
#include <queue>
const int MAX_VERTICES = 10000;
struct EdgeNode {
private:
int y{ -1 };
EdgeNode* next{ nullptr };
public:
EdgeNode(int _y,EdgeNode* _next) : y{ _y },next{ _next }{}
EdgeNode(int _y) : y{ _y },next{ nullptr}{}
const int getY() const { return y; } ;
const EdgeNode* const getNext() const { return next; };
};
class Graph {
EdgeNode* edges[MAX_VERTICES]{ nullptr };
int degree[MAX_VERTICES]{ 0 };
int totalVertices{ 0 };
int totalEdges{ 0 };
bool directed{ false };
bool processed[MAX_VERTICES]{ false };
bool discovered[MAX_VERTICES]{ false };
bool finished = false;
int parents[MAX_VERTICES];
void initializeSearch() {
for (int i = 0; i < MAX_VERTICES; i++)
{
parents[i] = -1;
processed[i] = false;
discovered[i] = false;
}
finished = false;
}
public:
int Vertices() const {return totalVertices; }
int Edges() const { return totalEdges; }
const EdgeNode* getEdge(int x) const {
if (x > MAX_VERTICES) return nullptr;
return edges[x];
}
bool insertEdge(int x,int y) { return insertEdge(x,y,false); }
bool insertEdge(int x,int y,bool _directed) {
if (x > MAX_VERTICES) { std::cout << std::endl << "Unable to insert edge. Max vertices allowed:" << MAX_VERTICES; return false; }
EdgeNode* temp = new EdgeNode(y,edges[x]);
if (degree[x] == 0) totalVertices++;
edges[x] = temp;
degree[x]++;
totalEdges++;
if (!_directed) {
insertEdge(y,x,true);
}
return true;
}
void process_vertex_late(int vertex) {}
void process_vertex_early(int vertex) {std::cout << std::endl << "Processing Vertex: " << vertex;}
void process_edge_dfs(int x,int y) {
std::cout << std::endl << "\tProcessing Edge(" << x << "," << y << ")";
if (discovered[y] && (parents[x] != y)) {
std::cout << std::endl << "Cycle(" << x << "," << y << ")";
std::cout << std::endl << std::endl;
finished = true;
}
}
void dfs1(int start) {
initializeSearch();
dfs(start,false);
}
void dfs(int v,bool print) {
const EdgeNode* p;
int y;
if (finished)
return;
discovered[v] = true;
process_vertex_early(v);
p = getEdge(v);
while (p != nullptr) {
y = p->getY();
if (!discovered[y]) {
parents[y] = v;
process_edge_dfs(v,y);
dfs(y,false);
}
else if (((!processed[y]) && (parents[v] != y)) || (directed))
{
process_edge_dfs(v,y);
if (finished)
return;
p = p->getNext();
}
}
process_vertex_late(v);
processed[v] = true;
}
};
int main()
{
Graph graph;
graph.insertEdge(1,2);
graph.insertEdge(1,5);
graph.insertEdge(1,6);
graph.insertEdge(2,5);
graph.insertEdge(2,3);
graph.insertEdge(3,4);
graph.insertEdge(4,5);
graph.dfs1(1);
return 0;
}
解决方法
希望你能找到答案。
我有这本书的第二版,我知道你的错误是什么。
你写的
else if (((!processed[y]) && (parents[v] != y)) || (directed))
{
process_edge_dfs(v,y);
if (finished)
return;
p = p->getNext();
}
正确的实现是:
else if (((!processed[y]) && (parents[v] != y)) || (directed))
process_edge_dfs(v,y);
if (finished) return;
p = p->getNext();
...
在我的版本中,代码在两页上,对齐方式不一样。 这很令人困惑。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。