栈的应用举例:迷宫求解

2017-07-23  本文已影响33人  output

参考严蔚敏老师的《数据结构》栈和队列这一章的相关内容完成的

栈的定义与基本操作的实现

/* 栈的顺序存储表示 */
#define STACK_INIT_SIZE 100
#define STACKINCREMENT  10
typedef struct
{
    ElemType *base;
    ElemType *top;
    int stacksize;
}SqStack;

/* 基本操作函数 9个 */

Status InitStack(SqStack *S)
{/* 01构造一个空栈 */
    S->base = (ElemType *)malloc(STACK_INIT_SIZE * sizeof(ElemType));
    if (!S->base)
    {
        printf("存储分配失败!:InitStack()\n");
        exit(OVERFLOW);
    }
    S->top = S->base;
    S->stacksize = STACK_INIT_SIZE;
    return OK;
}

Status DestroyStack(SqStack *S)
{/* 02销毁栈S */
    free(S->base);
    free(S->top);
    S->base = NULL;
    S->top = NULL;
    S->stacksize = 0;
    return OK;
}

Status ClearStack(SqStack S)
{/* 03把S设置为空栈 */
    S.top = S.base;
    return OK;
}

Status StackEmpty(SqStack S)
{/* 04查看栈是否为空 */
    return (S.top == S.base) ? TRUE : FALSE;
}

int StackLength(SqStack S)
{/* 05查看栈长度 */
    return (S.top-S.base)/sizeof(ElemType);
}

Status GetTop(SqStack S, ElemType *e)
{/* 06获取栈顶元素 */
    if (StackEmpty(S))
    {
        return FALSE;
    }
    else
    {
        *e = *(S.top-1);
    }
}

Status Push(SqStack *S, ElemType e)
{/* 07入栈 */
    if (StackLength(*S)==S->stacksize)
    {
        ElemType *newbase;
        newbase = (ElemType *)realloc(S, (S->stacksize+STACKINCREMENT)*sizeof(ElemType));
        if(!newbase)
        {
            printf("存储分配失败!:Push()\n");
            exit(OVERFLOW);
        }
        S->base = newbase;
        S->stacksize += STACKINCREMENT;
    }
    *(S->top) = e;
    S->top++;
    return OK;
}

Status Pop(SqStack *S, ElemType *e)
{/* 08出栈 */
    if (StackEmpty(*S))
    {
        return FALSE;
    }
    else
    {
        *e = *(--S->top);
    }
    return OK;
}

Status StackTraverse(SqStack S, Status (* visit)(ElemType e))
{/* 09遍历栈中元素 */
    while (S.top != S.base)
    {
        visit(*(--S.top));
    }
    printf("\n");
    return OK;
}

cbo3-1.c

迷宫求解的算法实现

typedef struct
{
    int x;  // 行号
    int y;  // 列号
} PosType;
typedef struct
{
    int ord;        // 序号
    PosType seat;   // 坐标
     int di;     // 方向 0123代表右下左上,默认向右
} ElemType;
#include "c1.h"
#include "cbo3-1.c"

/* 迷宫求解 */

/*
 * 地图
 * '#'    墙
 * ' '    路
 * 's'    入口
 * 'e'    出口
 * '*'  当前位置
 * 'o'  走过的路
 */
int map[10][10] = {{'#', '#', '#', '#', '#', '#', '#', '#', '#', '#'},
                   {'#', ' ', ' ', '#', ' ', ' ', ' ', '#', ' ', '#'},
                   {'#', ' ', ' ', '#', ' ', ' ', ' ', '#', ' ', '#'},
                   {'#', ' ', ' ', ' ', ' ', '#', '#', ' ', ' ', '#'},
                   {'#', ' ', '#', '#', '#', ' ', ' ', ' ', ' ', '#'},
                   {'#', ' ', ' ', ' ', '#', ' ', ' ', ' ', ' ', '#'},
                   {'#', ' ', '#', ' ', ' ', ' ', '#', ' ', ' ', '#'},
                   {'#', ' ', '#', '#', '#', ' ', '#', '#', ' ', '#'},
                   {'#', '#', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '#'},
                   {'#', '#', '#', '#', '#', '#', '#', '#', '#', '#'}};


PosType start;      // 入口坐标
PosType end;        // 出口坐标
SqStack ss;         // 栈
ElemType cur, top;  // 当前位置和栈顶位置


PosType direc[4] = {{0, 1},     // 右
                    {1, 0},     // 下
                    {0, -1},    // 左
                    {-1, 0}};    // 上
                    

int step = 0;       // 走的步数

/**
 * 打印地图有的
 */
void printMap();

int pass(PosType pt)
{ /* 判断该位置是否是通路 1:通路, 0:不是通路*/
    return map[pt.x][pt.y] == ' ' ? 1 : 0;
}

int isEnd(PosType pt)
{ /* 判断该位置是否是出口 1:是 0:不是 */
    int re = 0;
    if(pt.x == end.x && pt.y == end.y) {
        re = 1;
    }
    return re;
}

void print(ElemType e, char *s)
{ /* 打印栈元素 */
    printf("%s [e.ord:%d, e.seat(%d, %d), e.di:%d]\n", s, e.ord, e.seat.x, e.seat.y, e.di);
}

void setfoot(PosType pt, int op)
{ /* 设置脚印1:设置 0:清除 */
    if (map[pt.x][pt.y]==' ' && op==1)
    { // 只有在通路上设置脚印
        map[pt.x][pt.y] = 'o';
    }
    else if (map[pt.x][pt.y]=='o' && op==0)
    { // 清除脚印
        map[pt.x][pt.y] = ' ';
    }
}

int nextDi(ElemType e, ElemType *next)
{ /* next是e位置的下一个指向 */
    if (e.di<3)
    {
        next->di = 0;
        next->seat = e.seat;
        next->seat.x += direc[e.di+1].x;
        next->seat.y += direc[e.di+1].y;
    }
    else
    {   // 无路可走
        return 0;
    }
    return 1;
}

int main()
{
    /* 设置出口入口坐标 */
    start.x = 1;
    start.y = 1;
    end.x = 8;
    end.y = 8;

    /* 初始化当前位置 */
    cur.ord = 0;
    cur.seat = start;   // 设定当前位置的初值为入口坐标
    cur.di = 0;
    InitStack(&ss);
    
    printMap();
    
    int isStep=0;
    do {
        step++;
        if(isStep)
        {
            printf("\n******按回车键查看下一步******\n");
            getchar();
            printMap();
            isStep = 0;
        }
        if (pass(cur.seat))
        { // 若当前位置是通路
            cur.ord++;
            Push(&ss, cur);          // 将当前位置入栈
            setfoot(cur.seat, 1);    // 设置脚印
            print(cur, "当前位置入栈");
            isStep = 1;
            
            GetTop(ss, &top);
            if (isEnd(cur.seat))
            {   // 该位置是出口,则结束
                printf("pass! game over!\n");
                system("pause");
                
                return 0;
            }
            else
            {
                cur.seat.y++;   // 切换当前位置的右方为新的当前位置
                printf("当前位置向右移");
            }
        }
        else
        {  // 当前位置不通
            if (!StackEmpty(ss))
            { // 栈不空
                if (nextDi(top, &cur))
                { // 栈顶位置尚有其它方向,并且设定新的当前位置为顺时针方向旋转的栈顶位置的下一邻块
                    Pop(&ss, &top);
                    top.di++;
                    Push(&ss, top); // 修改栈顶元素的di
                    printf("修改栈顶位置的di");
                }
                else
                { // 栈顶位置的四周都不通
                    Pop(&ss, &top);         // 删除栈顶位置
                    setfoot(top.seat, 0);   // 清除脚印
                    print(top, "栈顶位置出栈");
                    isStep = 1;

                    GetTop(ss, &top);
                    if(!StackEmpty(ss))
                    { // 如果栈不空,则重新测试新的栈顶位置
                        GetTop(ss, &cur);
                    }
                    else
                    { // 栈为空,无结果
                        printf("no way\n");
                        break;
                    }
                }
            }
        }
    } while (!StackEmpty(ss));
    
    system("pause");
    return 0;
}

int visit(ElemType e) {
    printf("[ord:%d\t seat:(%d, %d) di:%d]\n", e.ord, e.seat.x, e.seat.y, e.di);
}

void printMap()
{
    printf("step = %d\n", step);
    print(cur, "当前位置");
    if(!StackEmpty(ss))
    {
        print(top, "栈顶位置");
        StackTraverse(ss, visit);
    }
    int i, j;   // i代表行,j代表列
    for (i=0; i<10; i++)
    {
        for (j=0; j<10; j++)
        {
            /*
            if (cur.seat.x==i && cur.seat.y==j)
            {
                printf("%c ", '*');

            }
            else if (start.x==i && start.y==j)
            {
                printf("%c ", 's');
            }
            else if (end.x==i && end.y==j)
            {
                printf("%c ", 'e');
            }
            else
            {
                printf("%c ", map[i][j]);
            }*/
            printf("%c ", map[i][j]);
        }
        printf("\n");
    }
    printf("\n");
}

main3-3.c

用到的一个包含文件

/* c1.h (程序名) */
 #include<string.h>
 #include<ctype.h>
 #include<malloc.h> /* malloc()等 */
 #include<limits.h> /* INT_MAX等 */
 #include<stdio.h> /* EOF(=^Z或F6),NULL */
 #include<stdlib.h> /* atoi() */
 #include<io.h> /* eof() */
 #include<math.h> /* floor(),ceil(),abs() */
 #include<process.h> /* exit() */
 /* 函数结果状态代码 */
 #define TRUE 1
 #define FALSE 0
 #define OK 1
 #define ERROR 0
 #define INFEASIBLE -1
 /* #define OVERFLOW -2 因为在math.h中已定义OVERFLOW的值为3,故去掉此行 */
 typedef int Status; /* Status是函数的类型,其值是函数结果状态代码,如OK等 */
 typedef int Boolean; /* Boolean是布尔类型,其值是TRUE或FALSE */

c1.h
上一篇下一篇

猜你喜欢

热点阅读