第二次在图上运行时,广度/深度优先搜索导致崩溃
Posted
技术标签:
【中文标题】第二次在图上运行时,广度/深度优先搜索导致崩溃【英文标题】:Breadth / Depth First Search causes crash when run on graph for second time 【发布时间】:2019-12-04 10:53:55 【问题描述】:所以我有一个已添加顶点和边的有向图。该图表示机场和它们之间的航班。当我运行广度优先或深度优先搜索以查找两个机场之间的路径时,我第一次得到正确答案,但是当我第二次使用完全相同的机场运行它时,它找不到路径并且程序崩溃错误代码-1073741819。几个小时以来,我一直试图弄清楚这一点,但我很困惑。 我运行了调试器,当 BFS 算法进入图形的 IsMarked() 函数时,问题似乎出现了。它无法读取 vertices[] 数组并且调试器说
这是我的图表类
#pragma once
#include "queue.h"
const int NULL_EDGE = 0;
template<class VertexType>
class GraphType
public:
GraphType(); // constructor, default of 50 vertices.
GraphType(int maxV); // parameterized constructor, maxV <= 50.
~GraphType(); // destructor
void MakeEmpty();
bool IsEmpty() const;
bool IsFull() const;
void AddVertex(VertexType);
void AddEdge(VertexType, VertexType, int);
int WeightIs(VertexType, VertexType);// (fromVertex, toVertex).
void GetToVertices(VertexType, QueType<VertexType>&);
void ClearMarks();
void MarkVertex(VertexType);
bool IsMarked(VertexType) const;
void DisplayFlights();
private:
int numVertices;
int maxVertices;
VertexType* vertices;
int edges[50][50];
bool* marks; // marks[i] is mark for vertices[i].
;
template<class VertexType>
GraphType<VertexType>::GraphType()
// Post: Arrays of size 50 are dynamically allocated for
// marks and vertices. numVertices is set to 0;
// maxVertices is set to 50.
numVertices = 0;
maxVertices = 50;
vertices = new VertexType[50];
marks = new bool[50];
//ClearMarks();
template<class VertexType>
GraphType<VertexType>::GraphType(int maxV)
// Post: Arrays of size maxV are dynamically
// allocated for marks and vertices.
// numVertices is set to 0; maxVertices is set to maxV.
numVertices = 0;
maxVertices = maxV;
vertices = new VertexType[maxV];
marks = new bool[maxV];
//ClearMarks();
template<class VertexType>
GraphType<VertexType>::~GraphType()
// Post: arrays for vertices and marks have been // deallocated.
delete[] vertices;
delete[] marks;
template<class VertexType>
void GraphType<VertexType>::MakeEmpty()
//not yet coded
template<class VertexType>
bool GraphType<VertexType>::IsEmpty() const
return (numVertices == 0);
template<class VertexType>
bool GraphType<VertexType>::IsFull() const
return (numVertices == maxVertices);
template<class VertexType>
void GraphType<VertexType>::AddVertex(VertexType vertex)
// Post: vertex has been stored in vertices.
// Corresponding row and column of edges have been
// set to NULL_EDGE.
// numVertices has been incremented.
//Not allowed to add duplicate vertex
bool duplicate = false;
for (int i = 0; i < numVertices; i++)
if (vertices[i] == vertex)
duplicate = true;
if (!duplicate)
vertices[numVertices] = vertex;
for (int index = 0; index < numVertices; index++)
edges[numVertices][index] = NULL_EDGE;
edges[index][numVertices] = NULL_EDGE;
numVertices++;
else
cerr << "Cannot add duplicate vertex\n";
template<class VertexType>
int IndexIs(VertexType * vertices,VertexType vertex)
// Post: Function value = index of vertex in vertices.
int index = 0;
while (!(vertex == vertices[index]))
index++;
return index;
template<class VertexType>
void GraphType<VertexType>::AddEdge(VertexType fromVertex,VertexType toVertex, int weight)
// Post: Edge (fromVertex, toVertex) is stored in edges.
/*int row;
int column;*/
int row = IndexIs(vertices, fromVertex);
int col = IndexIs(vertices, toVertex);
edges[row][col] = weight;
template<class VertexType>
int GraphType<VertexType>::WeightIs(VertexType fromVertex,VertexType toVertex)
// Post: Function value = weight associated with the
// edge (fromVertex, toVertex).
/*int row;
int column;*/
int row = IndexIs(vertices, fromVertex);
int col = IndexIs(vertices, toVertex);
return edges[row][col];
template<class VertexType>
void GraphType<VertexType>::GetToVertices(VertexType vertex, QueType<VertexType>& adjvertexQ)
int fromIndex;
int toIndex;
fromIndex = IndexIs(vertices, vertex);
for (toIndex = 0; toIndex < numVertices; toIndex++)
if (edges[fromIndex][toIndex] != NULL_EDGE)
adjvertexQ.Enqueue(vertices[toIndex]);
template<class VertexType>
void GraphType<VertexType>::ClearMarks()
for (int i = 0; i < maxVertices; i++)
marks[i] = false;
template<class VertexType>
void GraphType<VertexType>::MarkVertex(VertexType vertex)
for (int i = 0; i < numVertices; i++)
if (vertex == vertices[i])
marks[i] = true;
break;
/*int index = 0;
while (!(vertex == vertices[index]))
if (vertex == vertices[index])
marks[index] = true;
index++;
*/
template<class VertexType>
bool GraphType<VertexType>::IsMarked(VertexType vertex) const
for (int i = 0; i < numVertices; i++)
if (vertices[i] == vertex)
return marks[i];
template<class VertexType>
void GraphType<VertexType>::DisplayFlights()
//foreach vertex
QueType<VertexType> q;
VertexType adjVertex;
int weight;
for (int i = 0; i < numVertices; i++)
GetToVertices(vertices[i], q);
//get adjacent vertices
while (!q.IsEmpty())
q.Dequeue(adjVertex);
weight = WeightIs(vertices[i], adjVertex);
cout << vertices[i] << " to " << adjVertex << " " << weight << endl;
我的广度优先搜索
void BreadthFirstSearch(GraphType<string> graph, string startVertex, string endVertex)
// Assumes VertexType is a type for which the “==“ and “<<“
// operators are defined.
QueType<string> queue;
QueType<string> vertexQ;
bool found = false;
string vertex;
string item;
graph.ClearMarks();
queue.Enqueue(startVertex);
do
queue.Dequeue(vertex);
if (vertex == endVertex)
cout << vertex;
found = true;
else
if (!graph.IsMarked(vertex))
graph.MarkVertex(vertex);
cout << vertex << " ";
graph.GetToVertices(vertex, vertexQ);
while (!vertexQ.IsEmpty())
vertexQ.Dequeue(item);
if (!graph.IsMarked(item))
queue.Enqueue(item);
while (!queue.IsEmpty() && !found);
if (!found)
cout << "Path not found." << endl;
非常感谢任何帮助。非常感谢。
【问题讨论】:
您好,欢迎来到 ***。您应该将 BFS 中涉及的Graph
方法添加到您的问题中,例如GetToVertices
和Mark
、IsMarked
等,以便读者看到大部分涉及的代码。编写出错时输出的错误消息也会很有帮助。
如果你能创建一个Minimal Reproducible Example 会很有帮助。现在,我想,它与复制指针有关。当您将 BreadthFirstSearch 更改为 void BreadthFirstSearch(GraphType<string> &graph, string startVertex, string endVertex)
(按引用传递)时,是否也会出现此错误?
@churill 是的,将图表更改为通过引用传递似乎已经解决了问题。
【参考方案1】:
在void BreadthFirstSearch(GraphType<string> graph, string startVertex, string endVertex)
中,您通过值传递GraphType<string>
,这意味着创建了一个临时副本。那里的指针 vertices
和 marks
也被复制,但不是它们指向的值。
所以原始对象和临时对象都有指向相同内存位置的指针。
在BreadthFirstSearch
结束时,临时对象被销毁。在析构函数中,你 delete[]
vertices
和 marks
。
现在原始对象中的指针指向已释放的内存,这会导致未定义的行为。
最简单的解决方案是通过引用传递GraphType<string>
:
void BreadthFirstSearch(GraphType<string> &graph, string startVertex, string endVertex)
但为了安全起见,强烈建议使用std::vector,而不是手动管理内存。
【讨论】:
【参考方案2】:问题是,一旦你执行了你的算法,一旦图形以大量标记的顶点结束。您需要清除标记以进行第二次执行。
【讨论】:
以上是关于第二次在图上运行时,广度/深度优先搜索导致崩溃的主要内容,如果未能解决你的问题,请参考以下文章