数据结构与算法——附加作业二:走迷宫

《数据结构与算法》附加作业一报告:走迷宫

一、目的和要求(需求分析)

        1. 掌握栈的存储结构以及栈的建立和相关操作

        2. 利用栈完成迷宫求解。 

二、程序设计的基本思想,原理和算法描述

1. 建立一个带有栈顶和栈底指针的顺序栈。

原理:迷宫求解符合后进先出的规律,故使用栈完成。

2. 在迷宫原本图像周围附上一圈外墙。

        原理:使每个点都可以直接用相同方法判断是否可以通行,方便判断。

3. 用dfs完成对迷宫的求解。

        原理:用while循环语句,以右下左上四个方向对所在点可行进的方向进行判断,直到所在点为终点跳出循环。

4. 记录下dfs到达过的位置。

        原理:防止已判断过的位置继续判断,一直循环路径。

5. 用两个栈完成可行路线的正向输出。

        原理:栈为先进先出,若单纯一个栈的输出是结果的反向,故使用两个栈实现正向输出。

 

三、调试和运行程序过程中产生的问题及采取的措施:

1. 问题:刚开始不知道怎么建立一个栈。 

采取措施:通过看书,学习了创建链表。

2. 问题:不知道怎么写dfs。

        采取措施:通过查找网上的相关资料,掌握了dfs。

3. 问题:没有考虑到dfs到达过的位置重复判断造成路径循环的情况。

        采取措施:用特殊的值debug后发现问题,并对代码进行修改,添加了一个记录位置的函数。

4. 问题:没有正向输出结果。

        采取措施:利用两个栈,用一个栈反转另一个栈结果,使输出正向。

5. 问题:修改值时没有考虑到外部变量和内部变量。

     采取措施:函数传入的参数是局部变量,修改参数不能改变外部变量,故选用指针。

四、源程序及注释

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


//栈的顺序存储表示
#define STACK_INIT_SIZE 100 //存储空间初始分配化
#define STACK_INCREMENT 10 //存储空间分配增量

//栈ADT
//列举可行走法
enum steps {
    up, down, right, left
};
//定义栈存储的数据类型为迷宫中的一个点
typedef struct {
    int row; //行坐标
    int col; //列坐标
    enum steps nextStep;
} SElemType;
typedef struct {
    SElemType *base; //栈顶指针
    SElemType *top; //栈底指针
    int stackSize; //当前已分配的存储空间,以元素为单位
} SqStack;
SqStack InitStack();
void DestroyStack(SqStack S);
int StackEmpty(SqStack S);
SElemType *GetTop(SqStack S);
void Push(SqStack *S, SElemType e);
SElemType Pop(SqStack *S);

//栈的基本操作
//构造一个空栈S
SqStack InitStack() {
    SqStack S;
    S.base = (SElemType *) malloc(STACK_INIT_SIZE * sizeof(SElemType));
    if (!S.base) printf("内存分配失败!\n"); //存储分配失败
    S.top = S.base;
    S.stackSize = STACK_INIT_SIZE;
    return S;
}

//销毁栈S
void DestroyStack(SqStack S) {
    free(S.base);
}

//检验栈是否为空,若空返回1,否则返回0
int StackEmpty(SqStack S) {
    return S.base == S.top;
}

//访问栈顶元素并返回其指针
SElemType *GetTop(SqStack S) {
    if (S.top == S.base) printf("栈为空!\n");
    return S.top - 1;
}

//入栈
void Push(SqStack *S, SElemType e) {
    if (S->top - S->base >= S->stackSize) { //栈满,追加存储空间
        S->base = (SElemType *) realloc(S->base, (S->stackSize + STACK_INCREMENT) * sizeof(SElemType));
        if (!S->base) printf("内存分配失败!!\n");
        S->top = S->base + S->stackSize;
        S->stackSize += STACK_INCREMENT;
    }
    *S->top++ = e;
}

//出栈
SElemType Pop(SqStack *S) {
    if (S->top == S->base) printf("栈为空!\n");
    return *--S->top;
}


//迷宫数据结构及操作集
#define MAZE_WIDTH 10
#define MAZE_HEIGHT 10
void printMaze(int maze[MAZE_HEIGHT][MAZE_WIDTH]);
void record(int rooted[MAZE_HEIGHT][MAZE_WIDTH], int maze[MAZE_HEIGHT][MAZE_WIDTH]);
void MazePath(SqStack *S, int rooted[MAZE_HEIGHT][MAZE_WIDTH], SElemType start, SElemType end);
void PrintSolution(SqStack *S);

// 打印迷宫,"*"表示墙," "表示道路
void printMaze(int maze[MAZE_HEIGHT][MAZE_WIDTH]) {
    printf("迷宫图形如下:\n");
    for (int i = 0; i < MAZE_HEIGHT; i++) {
        for (int j = 0; j < MAZE_WIDTH; j++) {
            if (maze[i][j] == 1) printf("*");
            else printf(" ");
        }
        printf("\n");
    }
}

//记录迷宫中的点是否已被访问,若已被访问,值为1;否则为0.默认墙已被访问
void record(int rooted[MAZE_HEIGHT][MAZE_WIDTH], int maze[MAZE_HEIGHT][MAZE_WIDTH]) {
    for (int i = 0; i < MAZE_HEIGHT; i++)
        for (int j = 0; j < MAZE_WIDTH; j++)
            rooted[i][j] = maze[i][j]; //初始化
}

//用DFS找出通道
void MazePath(SqStack *S, int rooted[MAZE_HEIGHT][MAZE_WIDTH], SElemType start, SElemType end) {
    Push(S, start);
    while (!(GetTop(*S)->row == end.row && GetTop(*S)->col == end.col)) {
        SElemType *current;
        current = GetTop(*S);
        //右
        if (rooted[current->row][current->col + 1] != 1) {
            SElemType next = {current->row, current->col + 1, right};
            current->nextStep = right;
            rooted[current->row][current->col + 1] = 1;
            Push(S, next);
        }
        //下
        else if (rooted[current->row + 1][current->col] != 1) {
            SElemType next = {current->row + 1, current->col, right};
            current->nextStep = down;
            rooted[current->row + 1][current->col] = 1;
            Push(S, next);
        }
        //左
        else if (rooted[current->row][current->col - 1] != 1) {
            SElemType next = {current->row, current->col - 1, right};
            current->nextStep = left;
            rooted[current->row][current->col - 1] = 1;
            Push(S, next);
        }
        //上
        else if (rooted[current->row - 1][current->col] != 1) {
            SElemType next = {current->row - 1, current->col, right};
            current->nextStep = up;
            rooted[current->row - 1][current->col] = 1;
            Push(S, next);
        } else Pop(S);
    }
}

//打印迷宫解法
void PrintSolution(SqStack *S) {
    int num = 1;
    if (StackEmpty(*S)) printf("无解!\n");
    else {
        SqStack W = InitStack();
        while (!StackEmpty(*S)) {
            Push(&W, Pop(S));
        }
        while (!StackEmpty(W)) {
            SElemType *x = GetTop(W);
            if (x->nextStep == right) printf("第%d步 从(%d,%d)向右走到(%d,%d)\n", num, x->row, x->col, x->row, x->col + 1);
            if (x->nextStep == down) printf("第%d步 从(%d,%d)向下走到(%d,%d)\n", num, x->row, x->col, x->row + 1, x->col);
            if (x->nextStep == left) printf("第%d步 从(%d,%d)向左走到(%d,%d)\n", num, x->row, x->col, x->row, x->col - 1);
            if (x->nextStep == up) printf("第%d步 从(%d,%d)向上走到(%d,%d)\n", num, x->row, x->col, x->row - 1, x->col);
            Pop(&W);
            num++;
        }
    }
}


int main() {
    int row, col, i, j;
    SqStack S = InitStack();
    int maze[MAZE_HEIGHT][MAZE_WIDTH] = {
            // 1表示墙,0表示道路
            1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
            1, 0, 0, 1, 0, 0, 0, 1, 0, 1,
            1, 0, 0, 1, 0, 0, 0, 1, 0, 1,
            1, 0, 0, 0, 0, 1, 1, 0, 0, 1,
            1, 0, 1, 1, 1, 0, 0, 0, 0, 1,
            1, 0, 0, 0, 1, 0, 0, 0, 0, 1,
            1, 0, 1, 0, 0, 0, 1, 0, 0, 1,
            1, 0, 1, 1, 1, 0, 1, 1, 0, 1,
            1, 1, 0, 0, 0, 0, 0, 0, 0, 1,
            1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    };
    int rooted[MAZE_HEIGHT][MAZE_WIDTH];
    record(rooted, maze);

    printf("迷宫图像如下:\n");
    printMaze(maze);

    SElemType start = {1, 1, right};
    SElemType end = {8, 8, right};
    MazePath(&S, rooted, start, end);
    PrintSolution(&S);

    DestroyStack(S); // 释放栈内存
    return 0;
}

五、运行输出结果

 

六、心得与体会

        有了第一次附加作业的经历,花费很长时间去完成它已经习以为常,这也让我面对这些难题时更加耐心,磨得住性子。通过这次作业,我对于栈有了一定的掌握,也从知道有dfs深度搜索这个算法到会应用它。同时,我也知道了利用两个栈可以达到正向输出结果的目的。

  • 10
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阮阮的阮阮

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值