使用指针和引用,无法弄清楚为什么DFS无限重复

Using pointers and references, can't figure out why DFS is recurring infinitely

本文关键字:为什么 弄清楚 DFS 无限 指针 引用      更新时间:2023-10-16

我正在尝试使用自制的数据结构(HashMap和LinkedList(在有向图上实现一个简单的DFS来学习C++,但由于某种原因,DFS方法是无限循环的。

我认为它是无限重复的,因为由于某种原因,存储在哈希图(图形(中的节点实际上并没有在 DFS 期间被标记为访问。 我以为我理解了指针和参考,但显然我没有。如果有人能帮助我看到我做错了什么,我将不胜感激。

下面是无限重复的 DFS 方法:

template <class T>
bool Graph<T>::DFS(const T& v1, const T& v2) {
if(v1 == v2)
return true;
Graph<T>::Node * node = *(map->find(v1));
node->visited = true;
for(int i = 0; i < node->adjacent->size(); i++) 
if(node->adjacent->get(i).visited == false) 
return DFS(node->adjacent->get(i).data, v2);
return false;
}

这是 HashMap 类 find(( 方法

template <class K, class V>
V* HashMap<K, V>::find(const K& key) const {
int bucket = (int) hash_fn(key) % arrLength;
HashMap<K, V>::Node * temp = buckets[bucket];
while(temp != NULL && temp->key != key)
temp = temp->next;
if(temp == NULL)
return NULL;
else
return &(temp->value);
}

下面是图形类

template <class T>
class Graph {
struct Node {
T data;
bool visited;
LinkedList<Node> * adjacent;
Node() {
adjacent = nullptr;
visited = false;
}
Node(T data) {
this->data = data;
adjacent = new LinkedList<Node>();
visited = false;
}
};
public:
Graph();
~Graph();
void addEdge(const T& v1, const T& v2);
bool DFS(const T& v1, const T& v2);
private:
HashMap<T, Graph<T>::Node*> * map;
};
template <class T>
Graph<T>::Graph() {
map = new HashMap<T, Graph<T>::Node*>();
}
template <class T>
Graph<T>::~Graph() {
map->~Map<T, Graph<T>::Node*>();
}
template <class T>                                  // directed graph
void Graph<T>::addEdge(const T& v1, const T& v2) {  // add edge from v1 to v2
if(map->find(v1) == NULL)   
map->insert(v1, new Graph<T>::Node(v1));
if(map->find(v2) == NULL)
map->insert(v2, new Graph<T>::Node(v2));
(*map->find(v1))->adjacent->append( **map->find(v2) ); // oh god
}

下面是构造和填充图形的 Main 方法,然后调用 DFS 方法。

int main() {
Graph<int> * graph1 = new Graph<int>(); 
graph1->addEdge(1, 5);
graph1->addEdge(5, 9);
graph1->addEdge(9, 20);
graph1->DFS(1, 20);
return 0;
}

提前感谢您的任何帮助或见解。 -鲍勃

如果有的话,你对指针的使用看起来几乎是随机和任意的。你有指针没有意义的地方:HashMap<T, Graph<T>::Node*>,而缺乏应该有的指针:LinkedList<Node> * adjacent

您还可以在毫无意义的地方使用动态分配,例如Node的 afformentionadjacent成员,并且您的清理要么不存在(Graph::Node没有析构函数,而它应该有一个析构函数(,要么完全损坏(Graph<T>::~Graph()将导致有保证的内存泄漏(。

此外,没有任何内容可以清理你的visited标志,因此只需调用DFS即可。

坦率地说,你的代码在设计和实现方面都存在很多问题。

您的特定 DFS 问题可能来自对LinkedList<Node>而不是LinkedList<Node*>用于 adjency 列表,因为这可能会导致图形成为一个巨大的 DAG,其中子图形复制到 adjency 列表中,但如果不知道如何实现LinkedList<>,就很难判断。

编辑我只是直言不讳地说"这很糟糕",感觉有点糟糕,这是我正确实现代码的方法(使用 stl 而不是自定义容器(:

#include <unordered_map>
#include <vector>
template<typename T>
class Graph {
struct Node {
T data;
bool visited;
std::vector<Node*> adjacent;
Node(T const& d) : data(d), visited(false) {}
};
public:
inline void addEdge(T const& v1, T const& v2);
inline bool DFS(T const& v1, T const& v2);
private:
inline bool DFS_recur(T const& v1, T const& v2);
std::unordered_map<T, Node> map;
};
template<typename T>
void Graph<T>::addEdge(T const& v1, T const& v2) {
auto v1_found = map.emplace(v1, v1).first;
auto v2_found = map.emplace(v2, v2).first;
v1_found->second.adjacent.emplace_back(&v2_found->second);
}
template<typename T>
bool Graph<T>::DFS(T const& v1, T const& v2) {
auto result = DFS_recur(v1, v2);
// Return to the invariant state.
for(auto & n : map) {
n.second.visited = false;
}
return result;
}
template<typename T>
bool Graph<T>::DFS_recur(T const& v1, T const& v2) {
if(v1 == v2) return true;
auto v1_found = map.find(v1);
// If v1 is not in the map, we'll be in trouble.
if(v1_found == map.end()) return false;
v1_found->second.visited = true;
for(auto const & neighbour : v1_found->second.adjacent) {
if(!neighbour->visited) {
return DFS_recur(neighbour->data, v2);
}
}
return false;
}
int main() {
Graph<int> graph1;
graph1.addEdge(1, 5);
graph1.addEdge(5, 9);
graph1.addEdge(9, 20);
graph1.DFS(1, 20);
return 0;
}

请注意所有内存管理是如何通过 RAII 处理的,而不是newdelete