注意:我更喜欢c语言的算法或代码,提前谢谢。
假设我有一个 5x5 的二维数组。
00, 00, 01, 01, 00
01, 00, 01, 01, 00
01, 00, 00, 01, 01
01, 01, 00, 00, 00
01, 00, 00, 01, 01
分组标准 :- 阵列中所有从上、下、左、右或对角线相互连接的1(01)属于同一组。
现在,我想不递归地将所有 1 (01) 组合在一起,使我的数组看起来像:-
00, 00, 02, 02, 00
01, 00, 02, 02, 00
01, 00, 00, 02, 02
01, 01, 00, 00, 00
01, 00, 00, 03, 03
最后我输出有多少组。在这里,我输出 3。
假设我从一个索引位置找到连接,假设我在 i=1 和 j=0。 现在使用嵌套循环,我可以找到我所在位置的所有连接。
for(int i=-1; i<2; i++){
for(int j=-1; j<2; j++){
}}
但是我如何从一个连接中找到连接呢?假设我找到了来自 i=1, j=0 的所有连接。如果我在 i=1,j=1 处找到了 1,那么我如何再次继续搜索?这里的递归看起来很简单,但我应该如何在没有递归的情况下做到这一点?
这是我目前所拥有的。我没有时间限制,所以我这样做很愚蠢。
void printImgArray(int array[L][L])
{
printf("------ Image Contents -------\n");
int i, j;
for (i=0; i<L; i++)
{
for (j=0; j<L; j++)
printf("%02d, ",array[i][j]);
printf("\n");
}
printf("-----------------------------\n");
}
int checkIndex(int i, int j){
return i >= 0 && j>=0 && i< L && j< L;
}
int colorNonRecursively(int image[L][L]) {
int copyArray[L][L] = {0};
int i, j, new_i, new_j;
int counter = 1;
for(i=0; i<L; i++){
for(j=0; j<L; j++){
for(new_i=-1; new_i<2; new_i++){
for(new_j=-1; new_j<2; new_j++){
if(copyArray[i][j] != 1 && image[i][j] != 0){
copyArray[i][j] = 1;
image[i][j] = counter;
if(checkIndex(i+new_i, j+new_j)){
if(copyArray[i+new_i][j+new_j] != 1 &&
image[i+new_i][j+new_j] != 0){
copyArray[i+new_i][j+new_j] = 1;
image[i+new_i][j+new_j] = counter;
}
}
}
}
}
counter++;
}
}
int main(){
int cellImg[L][L]={{0,0,1,1,0},\
{1,0,1,1,0},\
{1,0,0,1,1},\
{1,1,0,0,0},\
{1,0,0,1,1}};
printImgArray(cellImg);
colorNonRecursively(cellImg);
printImgArray(cellImg);
return 0;
}
输入二维数组:-
00, 00, 01, 01, 00
01, 00, 01, 01, 00
01, 00, 00, 01, 01
01, 01, 00, 00, 00
01, 00, 00, 01, 01
输出二维数组:-
00, 00, 03, 04, 00
06, 00, 08, 09, 00
11, 00, 00, 14, 15
16, 17, 00, 00, 00
21, 00, 00, 24, 25
在这里我可以看到我的计数器放置在正确的位置,但分组没有正确完成。我知道这段代码的运行时间为 N^4,但在我的情况下这无关紧要,所以请忽略它。 我如何正确地将这些分组以便我将此数组作为输出?
输出二维数组(应该是):-
00, 00, 02, 02, 00,
01, 00, 02, 02, 00,
01, 00, 00, 02, 02,
01, 01, 00, 00, 00,
01, 00, 00, 03, 03,
答案 0 :(得分:2)
您可以创建该数组的图形表示,这样 1 是节点,边是相邻的 1。之后,您可以对这些节点进行 DFS 搜索,并将它们标记为已完成的 DFS 搜索。因此,如果是第一次 DFS 搜索,则标签为 1,如果是第二次 DFS/BFS 搜索,则为 2,依此类推。请注意,DFS/BFS 搜索的数量是连接组件的数量。这样你就有了一个带有你想要的标签的图表。之后,您可以根据需要将图形转换为数组。这也可以扩展到 n 维。您可以使用迭代方法进行图搜索。
答案 1 :(得分:2)
使用愚蠢的迭代和数据结构:
构建坐标集列表(数组中的索引):List<Set<Pair<Integer,Integer>>>
或 List<Set<Integer[]>>
在第一轮中,为列表中每个值为 1 的数组元素添加一个 Set。
在下一次迭代中循环遍历集合并检查 2 是否可以加入(更多循环)。删除 2 个集合并添加连接的集合。下一次迭代。
如果列表不再更改,您准备好组列表。
实施会很有趣,但我认为您想尝试一下...
我是对的,这很有趣(对不起,Java,但没有流):
public class Groups
{
public static void main(String[] args)
{
Integer[][] table = {
{00, 00, 01, 01, 00},
{01, 00, 01, 01, 00},
{01, 00, 00, 01, 01},
{01, 01, 00, 00, 00},
{01, 00, 00, 01, 01},
};
List<Set<Integer[]>> groups = createInitial(table);
groups = findgroups(groups);
print(table,groups);
}
private static void print(Integer[][] table, List<Set<Integer[]>> groups)
{
int groupid = 0;
for (Set<Integer[]> group : groups) {
groupid++;
for (Integer[] element : group) {
table[element[0]][element[1]] = groupid;
}
}
for (int i = 0; i < table.length; i ++) {
for (int j = 0; j < table[i].length; j ++) {
System.out.print(table[i][j]+ " ");
}
System.out.println();
}
}
private static List<Set<Integer[]>> findgroups(List<Set<Integer[]>> groups)
{
int before;
int after;
do {
before = groups.size();
join(groups);
after = groups.size();
} while (before != after);
return groups;
}
private static void join(List<Set<Integer[]>> groups)
{
for (int i = 0; i < groups.size(); i++) {
for (int j = i+1; j < groups.size(); j++) {
if (joins(groups.get(i),groups.get(j))) {
groups.get(i).addAll(groups.get(j)); // the joined group
groups.remove(j); // delete the other
return;
}
}
}
}
private static boolean joins(Set<Integer[]> group1, Set<Integer[]> group2)
{
for (Integer[] element1 : group1) {
for (Integer[] element2 : group2) {
if (adjacent(element1,element2)) {
return true;
}
}
}
return false;
}
private static boolean adjacent(Integer[] element1, Integer[] element2)
{
return ((Math.abs(element1[0] - element2[0]) < 2) && (Math.abs(element1[1] - element2[1]) < 2));
}
private static List<Set<Integer[]>> createInitial(Integer[][] table)
{
List<Set<Integer[]>> init = new ArrayList<>();
for (int i = 0; i < table.length; i ++) {
for (int j = 0; j < table[i].length; j ++) {
if (table[i] [j] > 0) {
Set<Integer[]> single = new HashSet<>();
Integer[] element = {i,j};
single.add(element);
init.add(single);
}
}
}
return init;
}
}
输出:
0 0 1 1 0
2 0 1 1 0
2 0 0 1 1
2 2 0 0 0
2 0 0 3 3
答案 2 :(得分:1)
循环遍历你的二维数组,每次遇到 1 并且索引未被访问时,运行 bfs。
在 bfs 期间,记住您已经访问过哪些索引(通过 bfs 或主循环)。这可以通过布尔数组来完成。
以下是一些c++代码。可以找到队列的 C 实现here
from multipledispatch import dispatch
@dispatch(int, int)
def add(x, y):
...
@dispatch(str, str)
def add(x, y):
...