无法找出无限循环背后的原因

Can't spot the reason behind infinite loop

我目前正在开发一个程序,它可以从形成轮廓的文件中读取一组坐标,然后使用 flood fill 算法填充它。

下面的代码似乎在无限循环中运行,但我似乎无法找出原因。

非常感谢您的帮助或建议:-)

    /* Flood fill */
    TargetColour = 0.0;
    NewColour = 2.0;
    starting_point = 0+slice;

    //Create queue
    queue < int > MyQue;
    //Insert first point into the queue
    MyQue.push(starting_point);

    //While loop for iterating over the nodes.
    while (!MyQue.empty()){
        //Take out the front element
        Node = MyQue.front();
        MyQue.pop();
        tmpSlice[Node] = NewColour;

        //Define the Node directions
        WestNode = Node-1;
        EastNode = Node+1;
        NorthNode = Node-sizes[1];
        SouthNode = Node+sizes[2];


        //East Node
        if (slab[EastNode] == TargetColour && floor((Node-sizes[1]*sizes[2]*floor(Node/(sizes[1]*sizes[2])))/sizes[1]) == floor((EastNode-sizes[1]*sizes[2]*floor(EastNode/(sizes[1]*sizes[2])))/sizes[1])){
            MyQue.push(EastNode);
        }
        //West Node
        if (slab[WestNode] == TargetColour && floor((Node-sizes[1]*sizes[2]*floor(Node/(sizes[1]*sizes[2])))/sizes[1]) == floor((WestNode-sizes[1]*sizes[2]*floor(WestNode/(sizes[1]*sizes[2])))/sizes[1])){
            MyQue.push(WestNode);
        }
        //North Node
        if (slab[NorthNode] == TargetColour && floor(Node / (sizes[1]*sizes[2])) == floor(NorthNode / (sizes[1]*sizes[2]))){
            MyQue.push(NorthNode);
        }
        //South Node
        if (slab[SouthNode] == TargetColour && floor(Node / (sizes[1]*sizes[2])) == floor(SouthNode / (sizes[1]*sizes[2]))){
            MyQue.push(SouthNode);
        }
    }

我部分确定您的算法实际上正在终止,但只是在很长一段时间后(假设队列有足够的内存)。我需要有关 sizes 值的更多详细信息才能完全确定。

让我们玩一个 3x3 的小示例字段,并假设整个 floor((Node-sizes[1]*sizes[2]*floor(Node/(sizes[1]*sizes[2])))/sizes[1]) 只是一个边界检查(它是什么?)。

字段(数字为职位名称):

1 2 3
4 5 6
7 8 9

假设starting_point = 1

  1. MyQue = { 1 }
    • 访问 1,将 2 和 4 添加到 MyQue
  2. MyQue = { 2, 4 }
    • 访问 2,将 3 和 5 添加到 MyQue
  3. MyQue = { 4, 3, 5 }
    • 访问 4,将 5 和 7 添加到 MyQue
  4. MyQue = { 3, 5, 5, 7 }
    • 访问 3,将 6 添加到 MyQue
  5. MyQue = { 5, 5, 7, 6 }
    • 访问 5,将 6 和 8 添加到 MyQue
  6. MyQue = { 5, 7, 6, 6, 8 }
    • 访问 5,将 6 和 8 添加到 MyQue
  7. MyQue = { 7, 6, 6, 8, 6, 8 }
    • 访问 7,将 8 添加到 MyQue
  8. MyQue = { 6, 6, 8, 6, 8, 8 }
    • 访问6,添加9到MyQue
  9. MyQue = { 6, 8, 6, 8, 8, 9 }
    • 访问6,添加9到MyQue
  10. MyQue = { 8, 6, 8, 8, 9, 9 }
    • 访问8,将9添加到MyQue
  11. MyQue = { 6, 8, 8, 9, 9, 9 }
    • 访问6,添加9到MyQue
  12. MyQue = { 8, 8, 9, 9, 9, 9 }
    • 访问8,将9添加到MyQue
  13. MyQue = { 8, 9, 9, 9, 9, 9 }
    • 访问8,将9添加到MyQue
  14. MyQue = { 9, 9, 9, 9, 9, 9 }
    • 访问 9
  15. MyQue = { 9, 9, 9, 9, 9 }
    • 访问 9
  16. MyQue = { 9, 9, 9, 9 }
    • 访问 9
  17. MyQue = { 9, 9, 9 }
    • 访问 9
  18. MyQue = { 9, 9 }
    • 访问 9
  19. MyQue = { 9 }
    • 访问 9

我希望这说明算法将如何经常重复相同的事情,即使对于一个小字段 - 这种效果会随着字段大小的增加而增加。

所以你能做的就是确保每个节点只排队一次。我认为评估顺序并不重要,因此您可以使用 set 来代替 queue 来存储工作集。这样可以保证每个号码同时只排队一次

您还可以组合队列和设置,以便保持评估顺序。

set < int > marker;
queue < int > MyQue;

// ... replace later in code
// MyQue.push(SomeNode);
// by
if (marker.insert(SomeNode).second) {
    MyQue.push(SomeNode);
}

编辑:稍微更改了 if 条件。如果插入 SomeNodemarker.insert(SomeNode).second 将是 true,如果 SomeNode 已经是集合的一部分,则 false