使用堆栈

时间:2019-04-16 13:56:34

标签: c

我只是通过递归对连接的组件标签进行编码 但是我想要使用堆栈和结构的非递归版本。

typedef struct _node{
int Xpos;
int Ypos;
int dir;    
}node;

node *stack[MAX];
node *push(node *t) {
stack[++top] = t;
return t;
}

node *pop() {
return stack[top--];
    }

结构组件确实具有Xposition和Yposition和Direction。 例如) if(t-> dir == 1){t-> Xpos = ++ t-> Xpos,t-> Ypos = --t-> Ypos}; 8邻居标签 我真的需要帮助! //编辑

//编辑 这是我通过递归所做的

#define MAP_SIZE 15
#define INILBCNT    10
int cnt = 1;
int input_map[MAP_SIZE][MAP_SIZE] =
{ {0,0,0,0,0,0,0,0,0,0,0,0,1,1,0},
{0,1,1,1,1,1,1,0,0,0,0,0,1,1,0},
{0,1,0,0,0,0,1,0,0,0,1,1,0,1,0},
{0,1,0,1,1,0,1,0,1,1,1,0,0,1,0},
{0,1,0,0,1,0,1,0,1,0,0,0,0,1,0},
{0,1,1,0,1,0,1,0,1,0,0,1,0,1,0},
{0,0,0,1,1,0,1,0,1,0,1,1,0,1,0},
{0,1,0,1,1,0,1,0,1,0,1,0,0,1,0},
{0,1,0,0,0,0,0,0,1,0,1,0,0,1,0},
{0,1,0,0,0,0,0,1,1,0,1,0,0,1,0},
{0,1,1,1,1,1,0,1,0,0,1,1,0,1,0},
{0,0,0,0,0,1,0,1,0,1,0,0,0,1,0},
{0,1,1,1,0,1,0,1,0,0,0,0,0,1,0},
{0,1,0,0,0,1,0,1,1,1,1,1,1,1,0},
{0,1,1,1,1,1,0,0,0,0,0,0,0,1,0}
};



void PrintMap()
{
system("cls");

for (int j = 0; j < MAP_SIZE; j++)
{
    for (int i = 0; i < MAP_SIZE; i++)
    {
        printf("%d ", input_map[j][i]);
    }
    printf("\n");   }  }

void glassFire(int mask_Y, int mask_X)
{

if (input_map[mask_Y][mask_X] != 1)
    return;
else
    if (input_map[mask_Y][mask_X] == 1)
    {
        input_map[mask_Y][mask_X] = cnt;            
        glassFire(mask_Y, mask_X + 1);
        glassFire(mask_Y + 1, mask_X);
        glassFire(mask_Y + 1, mask_X + 1);
        glassFire(mask_Y + 1, mask_X - 1);
        glassFire(mask_Y - 1, mask_X + 1);
        glassFire(mask_Y - 1, mask_X);
        glassFire(mask_Y - 1, mask_X + 1);
        glassFire(mask_Y, mask_X - 1); }}

void Serching()
{
PrintMap();
for (int i = 0; i < MAP_SIZE; i++)
{
    for (int j = 0; j < MAP_SIZE; j++)
    {

        if (input_map[j][i] == 1)
        {
            cnt++;
            glassFire(j, i);}
      }
   }
}

这段代码很好用。

1 个答案:

答案 0 :(得分:2)

  

这段代码很好用。

否,此代码具有未定义的行为,因为由于递归调用的添加/删除,您在input_map和/或mask_Y中读/写时mask_X和/或mask_Y的值为-1和/或15 1至mask_X / void glassFire(int mask_Y, int mask_X) { if (input_map[mask_Y][mask_X] != 1) return; else if (input_map[mask_Y][mask_X] == 1) { ... } }

void glassFire(int mask_Y, int mask_X)
{
   if ((mask_Y >= 0) && (mask_X >= 0) &&
       (mask_Y < MAP_SIZE) && (mask_X < MAP_SIZE) &&
       (input_map[mask_Y][mask_X] == 1))
   {
        ...
   }
}

第一个 if 没有用,但是您必须检查索引,可以是:

glassFire(mask_Y - 1, mask_X + 1);

您拨打两次glassFire(mask_Y - 1, mask_X - 1);,一次必须用丢失的 glassFire(mask_Y, mask_X + 1); glassFire(mask_Y + 1, mask_X); glassFire(mask_Y + 1, mask_X + 1); glassFire(mask_Y + 1, mask_X - 1); glassFire(mask_Y - 1, mask_X + 1); glassFire(mask_Y - 1, mask_X); glassFire(mask_Y - 1, mask_X - 1); /* modified */ glassFire(mask_Y, mask_X - 1); }} 代替。

而不是做

    static const YX offset[] = {
      {0,1}, {1,0}, {1,1}, {1,-1}, {-1,1}, {-1,0}, {-1,-1}, {0,-1}
    };

    for (int dir = 0; dir != 8; ++dir) 
      glassFire(mask_Y + offset[dir].y, mask_X + offset[dir].x);

您可以使用循环(这将有助于手动管理递归,减少代码量):

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

void glassFire(int mask_Y, int mask_X) { YX * stack = NULL; size_t sz = 0; size_t deep = 0; for (;;) { if (input_map[mask_Y][mask_X] == 1) /* need to check, can be false now */ { input_map[mask_Y][mask_X] = cnt; static const YX offset[] = { {0,1}, {1,0}, {1,1}, {1,-1}, {-1,1}, {-1,0}, {-1,-1}, {0,-1} }; /* up to 8 positions to save */ if ((deep + 8) > sz) { sz += 8; stack = realloc(stack, sz * sizeof(YX)); } for (int dir = 0; dir != 8; ++dir) { int ny = mask_Y + offset[dir].y; int nx = mask_X + offset[dir].x; if ((ny >= 0) && (nx >= 0) && (ny < MAP_SIZE) && (nx < MAP_SIZE) && (input_map[ny][nx] == 1)) { stack[deep].y = ny; stack[deep].x = nx; deep += 1; } } } if (deep == 0) /* empty */ break; deep -= 1; mask_Y = stack[deep].y; mask_X = stack[deep].x; } free(stack); }


要删除递归调用,您的包含方向的结构是不合适的,因为递归调用可以执行其他递归调用等,您只需要保存以后要管理的索引即可。

幸运的是,结果不取决于递归调用的顺序。

解决方案可以是:

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

#define MAP_SIZE 15
int cnt = 1;
int input_map[MAP_SIZE][MAP_SIZE] =
{ {0,0,0,0,0,0,0,0,0,0,0,0,1,1,0},
{0,1,1,1,1,1,1,0,0,0,0,0,1,1,0},
{0,1,0,0,0,0,1,0,0,0,1,1,0,1,0},
{0,1,0,1,1,0,1,0,1,1,1,0,0,1,0},
{0,1,0,0,1,0,1,0,1,0,0,0,0,1,0},
{0,1,1,0,1,0,1,0,1,0,0,1,0,1,0},
{0,0,0,1,1,0,1,0,1,0,1,1,0,1,0},
{0,1,0,1,1,0,1,0,1,0,1,0,0,1,0},
{0,1,0,0,0,0,0,0,1,0,1,0,0,1,0},
{0,1,0,0,0,0,0,1,1,0,1,0,0,1,0},
{0,1,1,1,1,1,0,1,0,0,1,1,0,1,0},
{0,0,0,0,0,1,0,1,0,1,0,0,0,1,0},
{0,1,1,1,0,1,0,1,0,0,0,0,0,1,0},
{0,1,0,0,0,1,0,1,1,1,1,1,1,1,0},
{0,1,1,1,1,1,0,0,0,0,0,0,0,1,0}
};

void PrintMap()
{
  for (int j = 0; j < MAP_SIZE; j++)
  {
    for (int i = 0; i < MAP_SIZE; i++)
    {
        printf("%d ", input_map[j][i]);
    }
    putchar('\n');
  }
}

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

void glassFire(int mask_Y, int mask_X)
{
  YX * stack = NULL;
  size_t sz = 0;
  size_t deep = 0;

  for (;;) {
    if (input_map[mask_Y][mask_X] == 1)
    {
      input_map[mask_Y][mask_X] = cnt;

      static const YX offset[] = {
        {0,1},  {1,0},  {1,1}, {1,-1}, {-1,1}, {-1,0}, {-1,-1},  {0,-1}
      };

      /* 8 positions to save */
      if ((deep + 8) > sz) {
        sz += 8;
        stack = realloc(stack, sz * sizeof(YX));
      }

      for (int dir = 0; dir != 8; ++dir) {
        int ny = mask_Y + offset[dir].y;
        int nx = mask_X + offset[dir].x;

        if ((ny >= 0) && (nx >= 0) &&
            (ny < MAP_SIZE) && (nx < MAP_SIZE) &&
            (input_map[ny][nx] == 1))
        {
          stack[deep].y = ny;
          stack[deep].x = nx;
          deep += 1;
        }
      }
    }

    if (deep == 0)
      /* empty */
      break;

    deep -= 1;
    mask_Y = stack[deep].y;
    mask_X = stack[deep].x;
  }

  free(stack);
}

void Serching() /* probably searching */
{
  PrintMap();

  for (int i = 0; i < MAP_SIZE; i++)
  {
    for (int j = 0; j < MAP_SIZE; j++)
    {
        if (input_map[j][i] == 1)
        {
          cnt++;
          glassFire(j, i);}
      }
   }
}

int main()
{
  Serching();
  putchar('\n');
  PrintMap();
}

如果我使用该完整程序(我删除了无用的 INILBCN ):

pi@raspberrypi:~ $ gcc -pedantic -Wall -Wextra c.c
pi@raspberrypi:~ $ ./a.out
0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 
0 1 1 1 1 1 1 0 0 0 0 0 1 1 0 
0 1 0 0 0 0 1 0 0 0 1 1 0 1 0 
0 1 0 1 1 0 1 0 1 1 1 0 0 1 0 
0 1 0 0 1 0 1 0 1 0 0 0 0 1 0 
0 1 1 0 1 0 1 0 1 0 0 1 0 1 0 
0 0 0 1 1 0 1 0 1 0 1 1 0 1 0 
0 1 0 1 1 0 1 0 1 0 1 0 0 1 0 
0 1 0 0 0 0 0 0 1 0 1 0 0 1 0 
0 1 0 0 0 0 0 1 1 0 1 0 0 1 0 
0 1 1 1 1 1 0 1 0 0 1 1 0 1 0 
0 0 0 0 0 1 0 1 0 1 0 0 0 1 0 
0 1 1 1 0 1 0 1 0 0 0 0 0 1 0 
0 1 0 0 0 1 0 1 1 1 1 1 1 1 0 
0 1 1 1 1 1 0 0 0 0 0 0 0 1 0 

0 0 0 0 0 0 0 0 0 0 0 0 4 4 0 
0 2 2 2 2 2 2 0 0 0 0 0 4 4 0 
0 2 0 0 0 0 2 0 0 0 4 4 0 4 0 
0 2 0 2 2 0 2 0 4 4 4 0 0 4 0 
0 2 0 0 2 0 2 0 4 0 0 0 0 4 0 
0 2 2 0 2 0 2 0 4 0 0 5 0 4 0 
0 0 0 2 2 0 2 0 4 0 5 5 0 4 0 
0 3 0 2 2 0 2 0 4 0 5 0 0 4 0 
0 3 0 0 0 0 0 0 4 0 5 0 0 4 0 
0 3 0 0 0 0 0 4 4 0 5 0 0 4 0 
0 3 3 3 3 3 0 4 0 0 5 5 0 4 0 
0 0 0 0 0 3 0 4 0 5 0 0 0 4 0 
0 3 3 3 0 3 0 4 0 0 0 0 0 4 0 
0 3 0 0 0 3 0 4 4 4 4 4 4 4 0 
0 3 3 3 3 3 0 0 0 0 0 0 0 4 0 

编译和执行:

cnt

我将input_map和{{1}}设为全局,但是它们可以位于 Serching 中,并可以为 glassFire 提供参数。全局变量越少越好。

请注意,我的代码产生的结果与您的代码(对校正结果取模)相同,但我不知道您的代码是否正确,因为我不知道它的真正作用是什么;-)