Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/147.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 广度优先搜索修剪和内存泄漏C++;_C++_Memory Leaks_Graph Theory_Breadth First Search - Fatal编程技术网

C++ 广度优先搜索修剪和内存泄漏C++;

C++ 广度优先搜索修剪和内存泄漏C++;,c++,memory-leaks,graph-theory,breadth-first-search,C++,Memory Leaks,Graph Theory,Breadth First Search,我在做一个项目,需要我解决一个你不能左转的迷宫。该程序运行良好,但在输入非常大的情况下除外 我的一般策略是将迷宫中的每个点设为图中的4个节点,对应于上、下、左和右,其中每个节点都有一条直边和右边,直边的权重为0,右边的权重为1。在我的代码中,边表示为一个对象,并且有一个指向is目标节点及其原始节点的指针 为了找到最佳路径(右转最少的路径),我使用了一个双端队列的广度优先搜索。我使用deque可以将权重1节点推到后面,将权重0节点推到前面。然而,我在搜索过程中分配了少量内存,并且没有在任何地方清理

我在做一个项目,需要我解决一个你不能左转的迷宫。该程序运行良好,但在输入非常大的情况下除外

我的一般策略是将迷宫中的每个点设为图中的4个节点,对应于上、下、左和右,其中每个节点都有一条直边和右边,直边的权重为0,右边的权重为1。在我的代码中,边表示为一个对象,并且有一个指向is目标节点及其原始节点的指针

为了找到最佳路径(右转最少的路径),我使用了一个双端队列的广度优先搜索。我使用deque可以将权重1节点推到后面,将权重0节点推到前面。然而,我在搜索过程中分配了少量内存,并且没有在任何地方清理它,这可能导致我的程序在非常大的迷宫输入中失败

以下是代码(特别是用于检查BFS内节点相邻边的for循环):

//t是图形中从deque弹出的节点对象
//从t检查每个相邻节点的循环(adj是边的向量)
for(无符号整数i=0;i已访问)
{
//内存泄漏位置
t、 adj[i].dest->prev=新节点(t);
t、 adj[i].used=true;
//如果是右转,则边的权重为1,否则为0
如果(t.adj[i].权重==1)
{
//将较重的节点放在队列的末尾
nodes.push_back(t.adj[i].dest);
}
//顶部的0权重节点
else节点。向前推(t.adj[i].dest);
}
}
我一直在试图找出如何更好地修剪搜索,以及如何在我肯定不再需要这些节点时释放此分配。但我需要一些关于如何考虑此问题的指导。如果需要其他代码,请告诉我

谢谢

编辑:节点和边缘类(请原谅我忽略了标准类设计原则,只是快速地将它们组合在一起):

类节点
{
公众:
node();
节点(方向d、整数r、整数c、节点类型t);
~node();//空定义
节点(常数节点*n);
节点(常数节点&n);
节点和运算符=(常量节点和n);
节点和运算符=(常量节点*n);
void addAdj(节点*a,int w);
void printAdj()常量;
字符串方向()常量;
无效打印()常量;

bool操作符如果
node
node::adj[]::dest::prev
的声明获取一个指向
t
(因此您不需要对
t
的类型(
node
?)进行完整定义,并为
t.adj[i].dest->prev
按值获取
node
(而不是动态分配)

这将确保您不会泄漏内存,因为您没有动态分配任何内容。缺点是您需要确保通过
dest::prev
t
的引用不在范围之内

在这种情况下,您可以更改线路

t.adj[i].dest->prev = new node(t);

您将需要一个特殊的值来表示无效的
prev
(以前为空)。也许可以使用
节点(空)


替代方法:使用共享指针(如果您不使用C++11,则BOOST会提供一个选择)以确保在所有引用都消失时自动解除分配。您必须确保不会永远保留循环引用,从而防止解除分配“zombi”节点(不再使用但无法释放的节点,因为仍然存在对它们的引用:
节点

如果
节点
使用指向
t
的指针(因此您不需要对
节点
的类型(
节点
?)的
节点::adj[]:dest::prev
声明进行完整定义,并按值获取
节点
)(而不是动态分配)用于
t.adj[i].dest->prev

这将确保您不会泄漏内存,因为您没有动态分配任何内容。缺点是您需要确保通过
dest::prev
t
的引用不在范围之内

在这种情况下,您可以更改线路

t.adj[i].dest->prev = new node(t);

您将需要一个特殊的值来表示无效的
prev
(以前为空)。也许可以使用
节点(空)


替代方法:使用共享指针(如果您不使用C++11,则BOOST会提供一个选择)以确保在所有引用都消失时自动解除分配。您必须确保不会永远保留循环引用,从而防止解除分配“zombi”节点(不再使用,但无法释放的节点,因为仍然存在对它们的引用

我的大脑没有完全理解您在这里要说的内容,您能试着再次解释一下吗?(我已经编写了几个小时的代码,所以我的大脑变得一团糟)编辑:遗憾的是,我不能使用boost或C++11,因为这是一个类项目,这些东西受到限制。您可以滚动您自己的共享指针实现,尽管这种方法肯定有很高的出错概率(一般来说是错误的)--关于第一个想法,请参见编辑以获得更多的澄清。我无法向您提供更多信息,因为我不知道您的结构/类。当我使用这行代码时,我会出现以下错误:“无法将赋值中的“node”转换为“node*”等一下,我会把我的节点和边缘类放在原始帖子中。是的,你需要重新设计你的结构/类以允许这种语法。我需要另一个某种类型的构造函数吗?我从来没有见过这种语法,所以我有点困惑。我的大脑还没有完全理解你在这里想说什么,你能再解释一下吗?(我已经写了好几年了
t.adj[i].dest->prev = new node(t);
t.adj[i].dest->prev = node(&t);