数据结构_迷宫求解

本文介绍了如何使用数据结构解决迷宫问题,包括递归和非递归两种方法的实现细节,并提供了相应的测试代码进行验证。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

定义迷宫

#include "seqstack.h"

#define MAX_ROW 6 //最大行数
#define MAX_COL 6 //最大列数

typedef struct Maze{
    int map[MAX_ROW][MAX_COL];//定义地图
}Maze;


void MazeInit(Maze* maze){//迷宫求解
    int map[MAX_ROW][MAX_COL]={
        { 0, 1, 0, 0, 0, 0 },
        { 0, 1, 1, 1, 0, 0 },
        { 0, 1, 1, 1, 1, 0 },
        { 0, 1, 1, 1, 0, 0 },
        { 0, 1, 1, 1, 0, 0 },
        { 0, 0, 0, 1, 0, 0 },
    };
    size_t i = 0;
    for(;i<MAX_ROW;++i){
        size_t j = 0;
        for(;j<MAX_COL;++j){
            maze->map[i][j] = map[i][j];
        }
    }
}

void MazePrint(Maze* maze){//迷宫打印
    size_t i = 0;
    for(;i<MAX_ROW;++i){
        size_t j = 0;
        for(;j<MAX_COL;++j){
            printf("%2d ",maze->map[i][j]);
        }
        printf("\n");
    }
        printf("\n");
}

引用头文件

#pragma once

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

#define FOR_MAZE

#ifdef FOR_MAZE
typedef struct Point{
    int row;
    int col;
}Point;

typedef Point SeqStackType;
#else
typedef char SeqStackType;
#endif

typedef struct SeqStack{
    SeqStackType* data;
    size_t size;
    size_t capacity;
}SeqStack;
void SeqStackInit(SeqStack* s);//栈初始化

void SeqStackPush(SeqStack* s,SeqStackType value);//压栈

void SeqStackReSize(SeqStack* s);//更改大小

void SeqStackPop(SeqStack* s);//出栈

int SeqStackTop(SeqStack* s,SeqStackType* value);//取栈顶元素

void SeqStackDestroy(SeqStack* s);//销毁

递归版本

//////////////////////////////////////////////////////////////////////////////////////
//              Round1 递归版本
/////////////////////////////////////////////////////////////////////////////////////

//是否能落脚,能返回1,不能返回0
int CanStay(Maze* maze,Point pt){
    //判断点是否在地图上
    if(pt.row < 0 || pt.row >= MAX_ROW || pt.col < 0 || pt.col >= MAX_COL){
        return 0;
    }
    int value = maze->map[pt.row][pt.col];
    if(value == 1){
        return 1;
    }
    return 0;
}

void Mark(Maze* maze,Point cur){
    maze->map[cur.row][cur.col] = 2;
    return;
}

int IsExit(Maze* maze,Point cur,Point entry){
    (void)maze;
    //如果当前点到了边界,即为找到了出口,但是不能是入口点
    if(cur.row == entry.row && cur.col == entry.col){
        return  0;
    }
    if(cur.row == 0 || cur.row == MAX_ROW-1 || cur.col == 0 || cur.col == MAX_COL-1){
        return 1;
    }
    return 0;
}

void _GetPath(Maze* maze,Point cur,Point entry){
    printf("row:%d col:%d\n",cur.row,cur.col);
    //1.判断当前点是否能落脚,不能落脚直接返回
    if(!CanStay(maze,cur)){
        return;
    }
    //2.如果能落脚,标记当前点
    Mark(maze,cur);
    //3.判断当前点是否为出口点,是则直接return
    if(IsExit(maze,cur,entry)){
        //找到了出口直接返回
        printf("找到了一条出路\n");
        return;
    }
    //4.判断当前点的上下左右是否有路可走,递归判断
    Point up = cur;
    up.row -= 1;
    _GetPath(maze,up,entry);

    Point right = cur;
    right.col += 1;
    _GetPath(maze,right,entry);

    Point down = cur;
    down.row += 1;
    _GetPath(maze,down,entry);

    Point left = cur;
    left.col -= 1;
    _GetPath(maze,left,entry);

}

void GetPath(Maze* maze,Point entry){
    if(maze == NULL){
        return;
    }
    //使用_GetPath辅助完成递归
    _GetPath(maze,entry,entry);
}

非递归版本

//////////////////////////////////////////////////////////////////////////////////////
//                  Round2 使用非递归版本
/////////////////////////////////////////////////////////////////////////////////////


void GetPathByLoop(Maze* maze,Point entry){
    if(maze == NULL){
        return;
    }
    SeqStackType cur;
    //手动维护一个栈,保存走过的路径
    SeqStack stack;
    SeqStackInit(&stack);
    //1.先判断是否能落脚,能落脚,当前点入栈
    if(!CanStay(maze,entry)){
        return;
    }
    SeqStackPush(&stack,entry);
    //2.如果能落脚,标记当前点
//    Mark(maze,entry);
    //循环取栈顶元素
    while(SeqStackTop(&stack,&cur)){
        Mark(maze,cur);
        if(IsExit(maze,cur,entry)){
        printf("找到了一条出路\n");
        return;
        }

        Point up = cur;
        up.row -= 1;
        if(CanStay(maze,up)){
//            Mark(maze,up);
            SeqStackPush(&stack,up);
            continue;
        }

        Point right = cur;
        right.col += 1;
        if(CanStay(maze,right)){
//            Mark(maze,right);
            SeqStackPush(&stack,right);
            continue;
        }

        Point down = cur;
        down.row += 1;
        if(CanStay(maze,down)){
//            Mark(maze,down);
            SeqStackPush(&stack,down);
            continue;
        }

        Point left = cur;
        left.col -= 1;
        if(CanStay(maze,left)){
//            Mark(maze,left);
            SeqStackPush(&stack,left);
            continue;
        }
        SeqStackPop(&stack);
    }
}

测试代码

//////////////////////////////////////////////////////////////////////////////////////
//                  以下为测试代码
/////////////////////////////////////////////////////////////////////////////////////

#if 1
#define TEST_HEADER printf("\n=========================%s=======================\n",__FUNCTION__)
void test(){
    TEST_HEADER;
    Maze maze;
    MazeInit(&maze);
    MazePrint(&maze);
    Point entry = {0,1};
    GetPath(&maze,entry);
    MazePrint(&maze);
}

void test2(){
    TEST_HEADER;
    Maze maze;
    MazeInit(&maze);
    MazePrint(&maze);
    Point entry = {0,1};
    GetPathByLoop(&maze,entry);
    MazePrint(&maze);

}

int main(){
    test();
    test2();
    return 0;
}
#endif

/* ****迷宫算法求解************* */ /**计目标:教学演示**************/ #include #define rows 10 #define cols 10 typedef struct {int row; int col; }PosType;/* //坐标点结构 */ typedef struct {int ord;/*//通道块在路径上的“序号” */ PosType seat;/*//通道块在迷宫中的“坐标位置”*/ int di;/*//从此通道快走向下一通道块的“方向” */ }SElemType;/*//栈的元素类型 */ typedef struct {SElemType *base; SElemType *top; int stacksize; }SqStack;/*//堆栈结构 */ void InitStack(SqStack &s)/*//初始化堆栈 */ { s.base=(SElemType *)malloc(100*sizeof(SElemType)); if(!s.base) return NULL; s.top=s.base; s.stacksize=100; } int StackEmpty(SqStack s)/* //栈空判别*/ {return(s.top==s.base); } void Pop(SqStack &s ,SelemType &e)/*//弹栈 */ {e=*--s.top); } void Push(SqStack &s,SElemType e)/*//将元素压入堆栈*/ { *s.top++=e; } /*static int maze[rows][cols]= {{0,0,0,0,0,0,0,0,0,0}, {0,1,1,0,1,1,1,0,1,0}, {0,1,1,0,1,0,1,0,1,0}, {0,1,1,0,1,0,0,1,1,0}, {0,1,1,0,0,1,1,1,1,0}, {0,1,1,1,0,1,1,1,1,0}, {0,1,0,1,1,1,0,1,1,0}, {0,1,0,0,0,1,0,0,1,0}, {0,0,1,1,1,1,1,1,1,0}, {0,0,0,0,0,0,0,0,0,0}, }; */ /* //初始迷宫数据(1-通,0-不通)*/ static int maze[rows][cols]= {{0,0,0,0,0,0,0,0,0,0}, {0,1,1,0,1,1,1,0,1,0}, {0,1,1,0,1,0,1,1,1,0}, {0,1,1,1,0,0,0,0,1,0}, {0,1,0,0,0,1,1,1,1,0}, {0,1,0,1,0,1,0,0,0,0}, {0,1,0,1,1,1,0,1,1,0}, {0,1,0,1,0,0,0,0,1,0}, {0,0,1,1,1,1,1,1,1,0}, {0,0,0,0,0,0,0,0,0,0}, }; /* //初始迷宫数据(1-通,0-不通)*/ static int foot[10][10]={0};/*//标记某点是否走过(1-走过,0-未走过)*/ void printpath(SqStack &s)/*//打印迷宫通路*/ {int i,j; SElemType e; while(!StackEmpty(s)) { Pop(s,e); foot[e.seat.row][e.seat.col]=1; } for(i=0;i<10;i++) {printf("\n"); for(j=0;j<10;j++) if(foot[i][j]) printf(" # "); else printf(" . "); } } int Pass(PosType pos)/*//判断当前的通道块是否可通*/ { return(maze[pos.row][pos.col]); }; void FootPrint(PosType pos) { maze[pos.row][pos.col]=0; } PosType NextPos(PosType curpos,int dir)/*//取当前通道块的下一个通道块*/ { switch(dir) {case 1: curpos.row++; break; case 2: curpos.col++; break; case 3: curpos.row--; break; case 4: curpos.col--; } return curpos;/*//将下一个通道块变为当前通道块*/ } int END(PosType curpos,PosType end) {return(curpos.row==end.row && curpos.col==end.col); } void MazePath(SqStack &s,PosType start,PosType end) {PosType curpos,nextpos; int curstep; SElemType e; SqStack *s; s=InitStack(); curpos=start; curstep=1; do{ if(Pass(curpos)) {FootPrint(curpos); e.ord=curstep;e.seat=curpos;e.di=1; Push(s,e); if(END(curpos,end)) return s; curpos=NextPos(curpos,1); curstep++; }/* end of if */ else { if(!StackEmpty(s)) { e=Pop(s); while(e.di==4 && !StackEmpty(s)) {FootPrint(e.seat);/* The same fuction as MarkPrint ? */ e=Pop(s); }/* end of while */ if(e.di<4) {e.di++;Push(s,e); curpos=NextPos(e.seat,e.di); } /* end of if */ } /* end of if */ } /* end of else */ }while(!StackEmpty(s)); curstep=0; return NULL; } void main() {SqStack *s; static PosType start={1,1},end={8,8}; s=MazePath(start,end); if(s) printpath(s); else printf("\n NO find the path!"); }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值