堆栈------迷宫算法

堆栈实现迷宫算法

/**
 * 迷宫问题
 * 迷宫用二维数组存储,0可走而1不可走
 * 1,1,1,1,1,1,1,1,1,1,1
 * 1,0,1,0,0,1,1,1,0,0,1
 * 1,0,0,0,0,0,1,0,0,1,1
 * 1,0,1,1,1,0,0,0,1,1,1
 * 1,0,0,0,1,0,1,1,0,1,1
 * 1,1,0,0,1,0,1,1,0,0,1
 * 1,1,1,0,0,0,0,0,0,0,1
 * 1,1,1,1,1,1,1,1,1,1,1
 */
#include <stdio.h>
#include <malloc.h>
typedef struct{
    int x,y;//xy代表东南西北移动的数据
}Direction;

typedef struct{
    int position_x,position_y;
    int direct;
}Box;

struct Stack{
    int MAXNUM;
    int top_position;
    Box* path;
};
typedef struct Stack* PStack;


PStack createEmptyStack(int size){
    PStack s = (PStack)malloc(sizeof(struct Stack));
    if(s != NULL)
    {
        s->path = (Box*)malloc(sizeof(Box)*size);
        if(s->path)
        {
            s->MAXNUM = size;
            s->top_position = -1;
            return s;
        }
        printf("Box 数组创建失败\n");
    }
    printf("Stack创建失败\n");
}

int isEmptyStack(PStack s){
    if(s->top_position == -1) return 1;
    return 0;
}


void push(PStack s,Box temp){
    if(s->top_position == (s->MAXNUM -1))
    {
        printf("Stack满载\n");
        return;
    }
    s->top_position++;
    s->path[s->top_position] = temp;
}

void pop(PStack s){
    if(isEmptyStack(s))
    {
        printf("空栈无法pop!\n");
        return;
    }
    s->top_position -= 1;
}

Box getTop(PStack s)
{
    if(isEmptyStack(s))
    {
        printf("空栈无数据\n");
    }
    return s->path[s->top_position];
}

void findExit(int map[8][11],Direction direction[]){
    PStack s = createEmptyStack(6*9); // s 用来存放路径的栈,大小为迷宫实际大小
    int x,y,d; //当前处理单元的x,y坐标以及方向度d
    int line,col; //下一个处理单元的行列坐标
    Box temp; //用于存储处理过的单元的x,y坐标以及方向度d的box,压入栈中的
    map[1][1] = -1; //起始位置为1,1,并且做已走过的标记-1
    temp.position_x = 1;
    temp.position_y = 1;
    temp.direct = -1; //-1,表示还没有探寻任何一个方向
    push(s,temp); //起点先压入栈中
    while(!isEmptyStack(s))//当栈不空时,还有找到出口的可能
    {
        temp = getTop(s); //当所有方向试探完毕,先用暂存获得最
        pop(s); //当所有方向试探完毕,则弹出最上方的元素,因为起跳的栈不在栈中
        //当前处理元素的数据即目前最顶层栈的数据
        x = temp.position_x;
        y = temp.position_y;
        d = temp.direct + 1;
        while(d<4)
        {
            //执行探寻操作 不同的d代表不同方向
            line = x + direction[d].x;
            col = y + direction[d].y;
            if(map[line][col] == 0) //如果下个单元可走
            {
                map[line][col] = -1; //标记为走过
                temp.position_x = x;
                temp.position_y = y;
                temp.direct = d;
                push(s,temp); //将起跳单元压入栈中,并将下个栈当作新起点,也就是正在处理的单元
                x = line;
                y = col;
                d = -1;
            }
            if(line == 6 && col == 9) //如果找到了出口
            {
                map[line][col] = -1; //标记为走过
                temp.position_x = line;
                temp.position_y = col;
                temp.direct = d;
                push(s,temp);
                while (!isEmptyStack(s))
                {
                    temp = getTop(s);
                    pop(s);
                    printf("(%d,%d)",temp.position_x,temp.position_y);
                }
                return;
            }
            d = d + 1;
        }
    }
    printf("没找到出口\n");
}

int main() {
    int map[8][11]={{1,1,1,1,1,1,1,1,1,1,1},
                    {1,0,1,0,0,1,1,1,0,0,1},
                    {1,0,0,0,0,0,1,0,0,1,1},
                    {1,0,1,1,1,0,0,0,1,1,1},
                    {1,0,0,0,1,0,1,1,0,1,1},
                    {1,1,0,0,1,0,1,1,0,0,1},
                    {1,1,1,0,0,0,0,0,0,0,1},
                    {1,1,1,1,1,1,1,1,1,1,1}};
    Direction direction[4];
    //东
    direction[0].x = 0;
    direction[0].y = 1;
    //南
    direction[1].x = 1;
    direction[1].y = 0;
    //西
    direction[2].x = 0;
    direction[2].y = -1;
    //北
    direction[3].x = -1;
    direction[3].y = 0;
    findExit(map,direction);
    return 0;
}

算法实现的关键

1.过多的if语句不利于判断,此时要想办法重构方法,去实现多if的情况。题目中的东南西北探寻,就被封装在了一个结构体数组中。
在这里插入图片描述
因为有4个方向需要探寻,所以用while循环即可控制

2.因此,栈中的元素类型也要发生相应的变化,我称作Box类型:
在这里插入图片描述
3.为什么在算法核心中,起点压入了栈中却又要弹出来?它究竟服务了什么?
首先,压入起点,是为了进入第一层循环。
至于为什么弹出来,我打个比方:
如果将迷宫理解为跳板迷宫,进入下一个单元必须是使用跳跃的动作,并且跳起的同时会将起跳单元踩出痕迹(也就是压入栈中)。算法中有两个概念,当前处理单元,下一个单元。**他们两个都是不在栈中的。**当前处理点就是你要起跳的点,下一个单元就是你渴望着陆的点。这么做的原因,是因为当走进死胡同时,我们需要退栈。当你跳入了死胡同的尽头,此时死胡同尽头还没有被压入栈中,因为我们并没有起跳,此时以死胡同尽头为起跳点,开始试探,发现四个方向都已经无法跳跃或者已经走过。这是需要退栈,取得上一个起跳点的所有数据,包括坐标,以及最关键的方向度,因为上一个点有可能没有考虑完所有的方向,取出所有的数据后,再将栈顶元素,也就是上一个起跳点弹出,相当于去除了原先起跳点的起跳很急,时光倒流回到了那个起跳点。再开始重新接着判断没有判断的方向,这样就可以保证探寻到每一个方向。这也就是能退栈,回到上一点的原因。

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值