Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.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
Algorithm 使用union find使用对角连接标记连接的零部件_Algorithm_Matrix_Connected Components - Fatal编程技术网

Algorithm 使用union find使用对角连接标记连接的零部件

Algorithm 使用union find使用对角连接标记连接的零部件,algorithm,matrix,connected-components,Algorithm,Matrix,Connected Components,我试图对我找到的连接组件算法进行修改,以回答这个问题: 基本上,我有由0和1组成的2d和3d矩阵。我的问题是找到1的连通区域,分别标记每个区域。矩阵大小可能非常大(由5e4乘5e4的二维元素和1000^3的三维元素组成)。所以我需要一种不会使堆栈内存紧张的东西,它足够快,可以在模拟过程中重复几次 使用深度优先搜索(depth-first search)对该问题的投票率最高的答案给出了一个堆栈溢出错误(如注释中所述)。我一直在尝试使用另一个用户建议的联合查找算法 原始代码(由用户Dukeling编

我试图对我找到的连接组件算法进行修改,以回答这个问题:

基本上,我有由0和1组成的2d和3d矩阵。我的问题是找到1的连通区域,分别标记每个区域。矩阵大小可能非常大(由5e4乘5e4的二维元素和1000^3的三维元素组成)。所以我需要一种不会使堆栈内存紧张的东西,它足够快,可以在模拟过程中重复几次

使用深度优先搜索(depth-first search)对该问题的投票率最高的答案给出了一个堆栈溢出错误(如注释中所述)。我一直在尝试使用另一个用户建议的联合查找算法

原始代码(由用户Dukeling编写)非常适用于大型二维矩阵,但我希望元素之间有对角连接。以下是我的代码,以及我尝试使用的示例输入:

#include <iostream>
#include <stdio.h>
#include <stdlib.h>

const int w = 8, h = 8;
int input[w][h] = {{1,0,0,0,1,0,0,1},
               {1,1,0,1,1,1,1,0},
               {0,1,0,0,0,0,0,1},
               {1,1,1,1,0,1,0,1},
               {0,0,0,0,0,0,1,0},
               {0,0,1,0,0,1,0,0},
               {0,1,0,0,1,1,1,0},
               {1,0,1,1,0,1,0,1}};
int component[w*h];

void doUnion(int a, int b)
{
// get the root component of a and b, and set the one's parent to the other
while (component[a] != a)
    a = component[a];
while (component[b] != b)
    b = component[b];
component[b] = a;
}

void unionCoords(int x, int y, int x2, int y2)
{
if (y2 < h && x2 < w && input[x][y] && input[x2][y2] && y2 > 0 && x2 > 0)
    doUnion(x*h + y, x2*h + y2);
}

int main()
{
int i, j;
for (i = 0; i < w*h; i++)
    component[i] = i;

for (int x = 0; x < w; x++)
for (int y = 0; y < h; y++)
{
    unionCoords(x, y, x+1, y);
    unionCoords(x, y, x, y+1);
    unionCoords(x, y, x+1, y+1);
    unionCoords(x, y, x-1, y+1);
    unionCoords(x, y, x+1, y-1);
    unionCoords(x, y, x-1, y-1);
}


// print the array
for (int x = 0; x < w; x++)
{
    for (int y = 0; y < h; y++)
    {
        if (input[x][y] == 0)
        {
            printf("%4d ",input[x][y]);
            continue;
        }
        int c = x*h + y;
        while (component[c] != c) c = component[c];
        printf("%4d ", component[c]);

    }
    printf("\n");
}
}
#包括
#包括
#包括
常数int w=8,h=8;
int输入[w][h]={{1,0,0,0,1,0,0,1},
{1,1,0,1,1,1,1,0},
{0,1,0,0,0,0,0,1},
{1,1,1,1,0,1,0,1},
{0,0,0,0,0,0,1,0},
{0,0,1,0,0,1,0,0},
{0,1,0,0,1,1,1,0},
{1,0,1,1,0,1,0,1}};
int分量[w*h];
无效双宁(内部a,内部b)
{
//获取a和b的根组件,并将其中一个的父组件设置为另一个
while(组件[a]!=a)
a=成分[a];
while(组件[b]!=b)
b=成分[b];
组分[b]=a;
}
无效联合坐标(整数x,整数y,整数x2,整数y2)
{
如果(y20&&x2>0)
双离子(x*h+y,x2*h+y2);
}
int main()
{
int i,j;
对于(i=0;i
如您所见,我添加了4个用于在元素之间进行对角连接的命令。这是对联合查找算法的有效修改吗?我特别搜索了Google和stackoverflow,但我找不到任何对角线连接的例子。此外,我想将其扩展到3维-因此我需要添加26个用于检查的命令。这种方式能很好地扩展吗?我的意思是代码似乎适用于我的情况,但有时我随机得到一个未标记的孤立元素。我不想仅仅为了几个月后发现一个bug而将它与我的代码集成


谢谢。

使用联合查找算法的方法没有问题。联合查找在任何图上运行。对于它检查的每个节点,它检查其连接的节点以确定它们是否在同一个子集中。您的方法似乎正在这样做,检查任何观察到的节点的8个相邻节点。联合查找算法与图形的维度无关。您可以将该方法扩展到三维或任何维度,只要图形与该维度正确对应。如果您遇到此错误,可以发布该错误的示例,或签出代码审阅:

您可以重写一个函数,将数组用作堆栈,而不是递归,然后直到内存耗尽,数组才会用完。如果goto可用,则不调用该函数,而是将返回地址的标记推送到堆栈上,然后转到其开始。开始时,从堆栈中弹出参数并继续。要返回,请弹出返回地址并转到那里。如果没有goto,则将函数转换为while循环。当堆栈上有任何事情要做时,尽你所能,将递归调用转化为todo对象到堆栈的推送。因此,在2d中,函数递归调用元素的四个邻居。它很快就耗尽了内存。我还将堆栈大小调整到了允许的最大限制。您好,谢谢您的回复。所以我甚至发布这个问题的原因是因为我无法让它在3d中工作。我想知道我在概念上是否有困难。如果你认为这样可以,我想我会编辑原始问题以包含3d代码。如果你将其作为一个单独的问题重新发布,你可能会得到更多的关注。此外,根据你新问题的性质,想一想它是属于这里还是属于代码审查?是的,我想你们是对的。我应该用非工作代码问一个新问题。好主意。另外,如果你认为这个答案在这个问题上帮了你很多忙,你可能想接受它,因为它不会把注意力从新的未回答的问题上移开。