在C中查找2D数组中的所有相邻元素

时间:2010-12-09 10:55:13

标签: c

我正在开展一个项目,有时候我被卡住了。

我的问题是例如我有以下2D数组包含3个不同的整数。

2 2 2 2 1 
1 2 2 2 1 
3 3 2 3 2 
3 1 3 3 1 
1 1 2 3 1 
1 3 1 3 3 

我想要的是找到数组中包含的任何数字的数组的最长相邻元素链。

与上面的数组一样,最长的链是数字2。

2 2 2 2
  2 2 2
    2

任何人都可以指导我为实现这一目标必须做些什么吗?

感谢。

5 个答案:

答案 0 :(得分:0)

假设您的矩阵是图形,并且元素是顶点。如果它们相邻且具有相同的值,则连接两个顶点。如果您在该图表中执行任何搜索,无论是Breadth-First Search还是Depth-First Search,您都会得到您想要的内容。 HTH

答案 1 :(得分:0)

绘制比解释更容易......

2 2 2 2 1 => A A A A B => (A: 4, B: 1)
1 2 2 2 1 => C A A A B => (A: 3 + 4, B: 1 + 1, C: 1)
3 3 2 3 2 => D D A E F => (A: 1 + 7, B: 2, C: 1, D: 2, E: 1, F: 1)
3 1 3 3 1 => D G E E G => (A: 8, B: 2, C: 1, D: 2 + 1, E: 2 + 1, F: 1, G: 1)
1 1 2 3 1 => ...
1 3 1 3 3 => ...

<强>更新

现在,有了一些真实的代码:

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

#define ROWS 6
#define COLS 5

unsigned char eles[ROWS][COLS] = { { 2, 2, 2, 2, 1 }, 
                                   { 1, 2, 2, 2, 1 }, 
                                   { 3, 3, 2, 3, 2 }, 
                                   { 3, 1, 3, 3, 1 }, 
                                   { 1, 1, 2, 3, 1 }, 
                                   { 1, 3, 1, 3, 3 } };

struct zone {
  int acu;
  int row, col;
  int refs;
};

typedef struct zone zone;

zone *
new_zone(int row, int col) {
  zone *z = (zone *)malloc(sizeof(zone));
  z->col = col;
  z->row = row;
  z->refs = 1;
  z->acu = 0;
}

void croak (const char *str) {
  fprintf(stderr, "error: %s\n", str);
  exit(1);
}

void
free_zone(zone *z) {
  if (z->refs != 0) croak("free_zone: reference count is not cero");
  free(z);
}

zone *
ref_zone(zone *z) {
  z->refs++;
  return z;
}

void
unref_zone(zone *z) {
  z->refs--;
  if (!z->refs) free_zone(z);
}

int
main() {
  zone *last[COLS];
  zone *current[COLS];
  zone *best = new_zone(0, 0);
  int i, j;
  memset(last, 0, sizeof(last));

  for (j = 0; j < ROWS; j++) {
    for (i = 0; i < COLS; i++) {
      unsigned int ele = eles[j][i];
      zone *z;
      /* printf("analyzing ele: %d at row %d, col: %d\n", ele, j, i); */
      if (i && (ele == eles[j][i-1])) {
        /* printf("  equal to left element\n"); */
        z = ref_zone(current[i-1]);
        if (j && (ele == eles[j-1][i])) {
          zone *z1 = last[i];
          /* printf("  equal to upper element\n"); */
          if (z != z1) {
            int k;
            /* printf("  collapsing zone %p\n", z1); */
            z->acu += z1->acu;
            for (k = 0; k < COLS; k++) {
              if (last[k] == z1) {
                last[k] = ref_zone(z);
                unref_zone(z1);
              }
            }
            for (k = 0; k < i; k++) {
              if (current[k] == z1) {
                current[k] = ref_zone(z);
                unref_zone(z1);
              }
            }
          }
        }
      }
      else if (j && (ele == eles[j-1][i])) {
        /* printf("  equal to upper element\n"); */
        z = ref_zone(last[i]);
      }
      else {
        /* printf("  new element\n"); */
        z = new_zone(j, i);
      }
      z->acu++;
      current[i] = z;
      /* printf("  element zone: %p\n", z); */
    }
    for (i = 0; i < COLS; i++) {
      if (j) unref_zone(last[i]);
      last[i] = current[i];
      if (best->acu < current[i]->acu) {
        unref_zone(best);
        best = ref_zone(current[i]);
        /* printf("best zone changed to %p at row; %d, col: %d, acu: %d\n", best, best->row, best->col, best->acu); */
      }
    }
  }
  printf("best zone is at row: %d, col: %d, ele: %d, size: %d\n", best->row, best->col, eles[best->row][best->col], best->acu);
}

答案 2 :(得分:0)

  1. 定义另一个相同大小的2d数组,将所有单元格初始化为0
  2. 将maxval设置为0
  3. 如果辅助数组满1,则转到5,否则找到0的单元格并执行:
    3.1将单元格的值更改为1
    3.2设置计数器为1
    3.3检查所有相邻的单元格,如果它们在辅助数组中为0,并且与输入数组中的当前单元格的值相同,则使用新的坐标计数器++并转到2.1。
  4. maxval = max(maxval,counter),转到3
  5. return maxval
  6. 步骤3.1-3.3应该实现为一个递归函数,它将坐标和两个数组作为参数,并返回1 +递归调用返回值的总和。

答案 3 :(得分:0)

您可以将其视为绘画应用程序中的图片。对2D数组中的每个元素执行flood-fill(除非它已被其他元素填充)并跟踪每个步骤中填充的像素数。

如果您的数组声明为

int elements[5][5];

然后引入第二个数组,告诉你是否已经填充了一个元素(如果你愿意的话,使用不同的类型,如bool,如果你的C程序没问题的话):

int pixelFilled[5][5];
memset( pixelFilled, 0, sizeof( pixelFilled ) );

接下来,写一个递归函数,它执行泛洪填充并返回已填充的元素数量(我从头顶写这个,不能保证这个函数按原样工作):

int floodFill( int x, int y ) {
  int filledPixels = 0;
  if ( !pixelFilled[x][y] ) {
    ++filledPixels;
    pixelFilled[x][y] = 1;
  }
  if ( x < 4 && elements[x+1][y] == elements[x][y])
    filledPixels += floodFill( x + 1, y );
  if ( x > 0 && elements[x-1][y] == elements[x][y] )
    filledPixels += floodFill( x - 1, y );
  if ( y < 4  && elements[x][y+1] == elements[x][y])
    filledPixels += floodFill( x, y + 1 );
  if ( y > 0  && elements[x][y-1] == elements[x][y])
    filledPixels += floodFill( x, y - 1 );
  return filledPixels;
}

最后,迭代你的数组并尝试完全填充它。跟踪最大的填充阵列:

int thisArea = 0;
int largestArea = 0;
int x, y;
for ( y = 0; y < 5; ++y ) {
  for ( x = 0; x < 5; ++x ) {
    thisArea = floodFill( x, y );
    if (thisArea > largestArea ) {
      largestArea = thisArea;
    }
  }
}

现在,largestArea应该包含相邻元素最长链的大小。

答案 4 :(得分:0)

我喜欢这种问题:-)所以这是我的答案。 正如Frerich Raabe所说,这可以通过floodFill函数来解决。例如,opencv库将提供现成的功能。

请原谅我,如果在下面的代码中你会发现C ++的痕迹,以防它们更容易被替换。

typedef struct Point {
   int x;
   int y;
} Point;

int areaOfBiggestContiguousRegion(int* mat,int nRows, int nCols) {
  int maxArea = 0;
  int currValue, queueSize, queueIndex;  
  int* aux;
  Point queue[1000]; //Stores the points I need to label
  Point newPoint, currentPoint;
  int x,y,x2,y2;
  //Code: allocate support array aux of same size of mat
  //Code: fill aux of zeros

  for (y = 0; y < nRows; y++)
    for (x = 0; x < nCols; x++)
      if (aux[y * nCols + x] == 0) {//I find a pixel not yet labeled, my seed for the next flood fill
        queueIndex = 0; //Contains the index to the next element in the queue
        queueSize = 0;

        currValue = mat[y * nCols + x]; //The "color" of the current spot
        aux[y * nCols + x] = 1;
        newPoint.x = x;
        newPoint.y = y;
        queue[queueSize] = newPoint;
        queueSize++; 

        while(queueIndex != queueSize) {
          currPoint = queue[queueIndex];
          queueIndex++;

          //Look left, right, up, down

          x2 = currPoint.x - 1;
          y2 = currPoint.y;
          //Some copy & paste, sorry I have been too long on C++ to remember correctly about C functions
          if (x2 >= 0 && aux[y2 * nCols + x2] == 0 && mat[y2 * nCols + x2] == currValue) {
            aux[y2 * nCols + x2] = 1;
            newPoint.x = x2;
            newPoint.y = y2;
            queue[queueSize] = newPoint;
            queueSize++; 
          }

          x2 = currPoint.x + 1;
          y2 = currPoint.y;
          //Some copy & paste, sorry I have been too long on C++ to remember correctly about C functions
          if (x2 < nCols && aux[y2 * nCols + x2] == 0 && mat[y2 * nCols + x2] == currValue) {
            aux[y2 * nCols + x2] = 1;
            newPoint.x = x2;
            newPoint.y = y2;
            queue[queueSize] = newPoint;
            queueSize++; 
          }

          x2 = currPoint.x;
          y2 = currPoint.y - 1;
          //Some copy & paste, sorry I have been too long on C++ to remember correctly about C functions
          if (y2 >= 0 && aux[y2 * nCols + x2] == 0 && mat[y2 * nCols + x2] == currValue) {
            aux[y2 * nCols + x2] = 1;
            newPoint.x = x2;
            newPoint.y = y2;
            queue[queueSize] = newPoint;
            queueSize++; 
          }

          x2 = currPoint.x;
          y2 = currPoint.y + 1;
          //Some copy & paste, sorry I have been too long on C++ to remember correctly about C functions
          if (y2 < nRows && aux[y2 * nCols + x2] == 0 && mat[y2 * nCols + x2] == currValue) {
            aux[y2 * nCols + x2] = 1;
            newPoint.x = x2;
            newPoint.y = y2;
            queue[queueSize] = newPoint;
            queueSize++; 
          }
        } //while

      if (queueSize > maxArea)
        maxArea = queueSize; //If necessary we could store other details like currentValue
      }//if (aux...

return maxArea;
}

注意:在C ++中使用std容器和Point的构造函数,它变得更加紧凑