数据结构:带环迷宫如何求最短路径(栈)


遇到下一位为1,或者下一位置大于当前位置,则为通路

向后走是,将前一个节点值+1,标记节点

按照上-左-右-下的顺序

简单迷宫实现:栈结构实现:迷宫出口判断 - CSDN博客 https://blog.csdn.net/W_J_F_/article/details/80165506 

递归实现迷宫:数据结构:递归实现简单迷宫 - CSDN博客 https://blog.csdn.net/W_J_F_/article/details/80233310 

栈实现:数据结构:静态栈与动态栈的实现 - CSDN博客 https://blog.csdn.net/W_J_F_/article/details/80082296 




maze.h

#pragma once  
#define MAX_ROW 6  
#define MAX_COL 6  

typedef struct Position
{
	int _x;
	int _y;
}Position;

typedef struct Maze
{
	int _map[MAX_ROW][MAX_COL];

}Maze, *PMaze;

// 栈的初始化   
void InitMaze(Maze *m, int map[][MAX_COL]);

// 检测入口是否为有效入口   
int IsValidEntry(Maze *m, Position entry);

// 检测cur位置是否是通路   
int IsPass(Maze *m, Position cur, Position next);

// 检测Cur是否在出口   
int IsExit(Maze *m, Position cur, Position entry);

// 走迷宫   
void PassMaze(Maze *m, Position entry, Stack* shortPath);

// 打印迷宫   
void PrintMaze(Maze *m);

void SaveShortPath(Stack* path, Stack* shortPath);

void _PassMaze(Maze* m, Position entry, Position cur, Stack* path, Stack* shortPath);

maze.c

#include "stack.h"  
#include "Maze.h"  

//1. 用栈对简单迷宫进行求解,迷宫只有一个出口  
//采用循环方式实现  

void PrintMaze(Maze *m)//打印迷宫  
{
	int i = 0;
	assert(m);

	for (; i < MAX_ROW; ++i)
	{
		int j = 0;
		for (; j < MAX_COL; ++j)
		{
			printf("%d ", m->_map[i][j]);
		}
		printf("\n");
	}

}

void InitMaze(Maze *m, int map[][MAX_COL])//迷宫初始化,就是将地图中的值赋给迷宫  
{
	int i = 0;
	assert(m);

	for (; i < MAX_ROW; ++i)
	{
		int j = 0;
		for (; j < MAX_COL; ++j)
		{
			m->_map[i][j] = map[i][j];
		}
	}
}

int IsValidEntry(Maze *m, Position entry)//检测迷宫入口是否合法  
{
	assert(m);

	//必须位于迷宫边界且值为1  
	if ((entry._x == 0 || entry._y == 0 || entry._x == MAX_ROW - 1
		|| entry._y == MAX_COL - 1) && (m->_map[entry._x][entry._y] == 1))
		return 1;
	return 0;
}

int IsPass(Maze *m, Position cur, Position next)// 检测cur位置是否是通路   
{
	assert(m);

	//值为1且不能越界  
	if ((next._x >= 0 && next._x <= MAX_ROW - 1) &&
		(next._y >= 0 && next._y <= MAX_COL - 1) &&
		m->_map[next._x][next._y] == 1 ||                   //如果迷宫没走过 值为1则为通路
		m->_map[next._x][next._y] > m->_map[cur._x][cur._y])//如果迷宫走过,next>cur则为通路
		return 1;

	return 0;

}

int IsExit(Maze *m, Position cur, Position entry)// 检测Cur是否在出口   
{
	assert(m);

	//出口位置就是处于边界值为1且不能是入口  
	if ((cur._x == 0 || cur._y == 0 || cur._x == MAX_ROW - 1
		|| cur._y == MAX_COL - 1) && (m->_map[cur._x][cur._y] == 1)
		&& ((cur._x != entry._x) || (cur._y != entry._y)))
		return 1;

	return 0;
}

void PassMaze(Maze *m, Position entry, Stack* shortPath)
{
	Stack path;
	//检测入口是否合法
	if (!IsValidEntry(m, entry))
	{
		printf("迷宫非法!\n");
		return;
	}
	StackInit(&path,100);
	_PassMaze(m, entry, entry, &path, shortPath);
	int i = 0;
	int size = StackSize(shortPath);
	for (;i < size;++i)
	{
		printf("[%d][%d]->", shortPath->arr[i]._x, shortPath->arr[i]._y);
	}

}

void _PassMaze(Maze* m, Position entry, Position cur, Stack* path, Stack* shortPath)
{
	Position next;
	if (StackEmpty(path))
		m->_map[cur._x][cur._y] = 2;
	
	StackPush(path,cur);
	
		printf("[%d][%d]->", cur._x, cur._y);

	if (IsExit(m, cur, entry))//判断是否是出口
	{
		if(StackEmpty(shortPath) || StackSize(path) > StackSize(shortPath))
			SaveShortPath(path,shortPath);
		StackPop(path);
		return;
	}
	//上
	next = cur;
	next._x -= 1;
	if (IsPass(m, cur, next))
	{
		m->_map[next._x][next._y]= m->_map[cur._x][cur._y] + 1;
		_PassMaze(m,entry,next,path,shortPath);
	}
	//左
	next = cur;
	next._y -= 1;
	if (IsPass(m, cur, next))
	{
		m->_map[next._x][next._y] = m->_map[cur._x][cur._y] + 1;
		_PassMaze(m, entry, next, path, shortPath);
	}
	//右
	next = cur;
	next._y += 1;
	if (IsPass(m, cur, next))
	{
		m->_map[next._x][next._y] = m->_map[cur._x][cur._y] + 1;
		_PassMaze(m, entry, next, path, shortPath);
	}
	//下
	next = cur;
	next._x += 1;
	if (IsPass(m, cur, next))
	{
		m->_map[next._x][next._y] = m->_map[cur._x][cur._y] + 1;
		_PassMaze(m, entry, next, path, shortPath);
	}
	
}

void SaveShortPath(Stack* path, Stack* shortPath)
{
	int i = 0,size;
	assert(path);
	assert(shortPath);
	size = StackSize(path);
	for (;i < size;++i)
	{
		shortPath->arr[i] = path->arr[i];
	}
	shortPath->size = i;
	
}

test()

#include "stack.h"  
#include "maze.h"  

void TestMaze()
{
	Position entry;
	Maze m;
	Stack s;
	Stack path;
	int map[6][6] = {
	{ 0,0,0,0,0,0 },
	{ 0,1,0,0,0,0 },
	{ 0,1,1,1,1,0 },
	{ 0,1,0,0,1,1 },
	{ 0,1,1,1,1,0 },
	{ 0,1,0,0,0,0 }, 
	};
	StackInit(&s, 10);
	StackInit(&path, 10);

	InitMaze(&m, map);

	PrintMaze(&m);
	entry._x = 5;
	entry._y = 1;

	printf("\n");
	PassMaze(&m, entry, &s);
	printf("\n");

	printf("\n");
	PrintMaze(&m);

}
int main()
{
	TestMaze();//测试迷宫  
	system("pause");
	return 0;
}

stack.c

#include "stack.h"  
#include "maze.h"  

void StackInit(Stack *S, int capacity)//栈初始化  
{
	S->arr = (DataType*)malloc(capacity * sizeof(DataType));
	if (NULL == S->arr)
	{
		printf("申请空间失败!\n");
		return;
	}
	S->capacity = capacity;
	S->size = 0;
}


void AddCapacity(Stack *S)//扩容  
{
	if (NULL == S->arr)
	{
		printf("扩容失败\n");
		return;
	}
	S->capacity = (DataType*)realloc(S->arr, sizeof(DataType) * (S->capacity) * 2);//扩容为原来的二倍  
	if (NULL == S->arr)
	{
		printf("空间扩增失败!!!\n");
		return;
	}
	S->capacity = 2 * (S->capacity);
}

void PrintfStack(Stack *S)//打印栈  
{
	int i = 0;
	if (NULL == S->arr)
	{
		printf("打印失败\n");
		return;
	}
	for (;i<S->size;i++)
	{
		printf("%d \n", &S->arr[i]);
	}
	printf("\n");
}

void StackPush(Stack *S, DataType data)//入栈  
{
	if (NULL == S->arr)
	{
		printf("入栈失败\n");
		return;
	}
	if (S->capacity == S->size)//空间已满  
	{
		AddCapacity(S);
	}
	S->arr[S->size] = data;
	S->size++;
}

void StackPop(Stack *S)//出栈  
{
	if (NULL == S->arr)
	{
		printf("出栈失败\n");
		return;
	}
	S->size--;
}

DataType StackTop(Stack *s)//获取栈顶元素  
{
	return s->arr[s->size - 1];
	/* int ret = 0;
	if(NULL == S->arr)
	{
	printf("获取栈失败\n");
	return;
	}
	if(0 == S->size)
	{
	printf("栈为空!\n");
	return;
	}

	printf("栈顶元素为:%d \n", S->arr[S->size - 1]);*/
}

int StackSize(Stack *S)//获取元素个数  
{
	if (NULL == S->arr)
	{
		printf("获取栈失败\n");
		return 0;
	}
	return S->size;
	//printf("元素个数为:%d\n", S->size);
}

int StackEmpty(Stack *S)//检测栈是否为空  
{
	if (NULL == S->arr)
	{
		printf("获取栈失败\n");
		return 0;
	}
	if (S->size == 0)
	{
		return 1;
	}
	return 0;
}

stack.h

#pragma once  
#include <assert.h>  
#include <stdio.h>  
#include <stdlib.h>  
#include <string.h>  

typedef struct Position DataType;

typedef struct Stack
{
	DataType *arr;//指向动态空间的指针  
	int capacity;//空间总容量  
	int size;//有效元素个数  
}Stack, *PStack;

// 栈的初始化   
void StackInit(Stack *S, int capacity);

// 入栈   
void StackPush(Stack *S, DataType data);

// 出栈   
void StackPop(Stack *S);

// 获取栈顶元素   
DataType StackTop(Stack *S);

// 获取栈中元素个数   
int StackSize(Stack *S);

// 检测栈是否为空   
int StackEmpty(Stack *S);

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
#include #include #define N1 9 #define N2 8 #define T N1*N2 #define M 4 char B[N1+1][N2+1]; int count=0; //记录路径条数 typedef struct node1 { int a1; int a2; }find,direct[M+1]; typedef struct { int b1; int b2; int id; }site; typedef struct //顺序 { site ht[T]; int top; }Stack; void Push(Stack *s,int a,int b) { s->top++; s->ht[s->top].b1=a; s->ht[s->top].b2=b; } void Gettop(Stack * s,int *a,int *b) { *a=s->ht[s->top].b1; *b=s->ht[s->top].b2; } void create(char *a) //从文件读出迷宫(正确) { int i=0,j=0,p=1; char x; FILE *fp; fp=fopen("in.txt","r"); if(fp==NULL) { printf("文件不能打开!\n"); exit(0); } x=fgetc(fp); while(x!=EOF) { if(x=='0') { i++; a[i]=x; } if(x=='1') { i++; a[i]=x; } x=fgetc(fp); } printf(" ~~~~~~~生成迷宫~~~~~~~\n"); x=fgetc(fp); while(p<=T) //用二维数组b记录迷宫每个位置是否可行 { for(i=1;i<=N1;i++) for(j=1;j<=N2;j++) { B[i][j]=a[p]; p++; } } printf(" "); printf("■■■■■■■■■■■■\n"); printf(" ■"); printf(" ■\n"); for(i=1;i<=N1;i++) { printf(" "); printf("■ "); for(j=1;jht[s1->top].id=id; B[x][y]='*'; while(s1->top>0) { Gettop(s1,&x,&y); id=s1->ht[s1->top].id; if(x==B1&&y==B2) { count++; fprintf(fp,"%d%c%c",count,':',' '); printf("第 %d 条路径(长度为%d):\n",count,s1->top); s1->ht[s1->top].id=0; for(i=1;itop;i++) { printf("(%d,%d,%d)->",s1->ht[i].b1,s1->ht[i].b2,s1->ht[i].id); fprintf(fp,"%c%d%c%d%c%d%c%c",'(',s1->ht[i].b1,',',s1->ht[i].b2,',',s1->ht[i].id,')',' '); if(i==0) fprintf(fp,"%c%c%c%c",'\n',' ',' ',' '); if(i%8==0) printf("\n"); } fprintf(fp,"%c",'\n'); printf("结束!\n\n"); if(s1->toptop=s1->top; min=s1->top; for(i=1;itop;i++) s2->ht[i]=s1->ht[i]; } B[x][y]='0'; s1->top--; //退(s1->top--) Gettop(s1,&x,&y); id=s1->ht[s1->top].id; } fun=0; while(idht[s1->top].b1; y=s1->ht[s1->top].b2; x=x+p[id].a1; y=y+p[id].a2; if(x==0||y==0||x>N1||y>N2) continue; if(B[x][y]=='0') { fun=1; break; } } if(fun==1) //找到通路 { s1->ht[s1->top].id=id; Push(s1,x,y); B[x][y]='*'; s1->ht[s1->top].id=0; } else { x=s1->ht[s1->top].b1; y=s1->ht[s1->top].b2; B[x][y]='0'; s1->top--; } } if(count==0) printf(" 无路径!\n"); else { printf("\n\n\n "); printf("所有路径已存储在文件%s 中,请去查找!\n\n",filename); } return 1; } void Print(Stack *s2,char filename[]) { int i; FILE *fp; fp=fopen(filename,"a+"); if(fp==NULL) { printf("文件不能打开!\n"); exit(0); } if(count!=0) { fprintf(fp,"%s","最短路径为:"); fprintf(fp,"%c",'\n'); printf(" "); printf("%s\n","**********最短路径**********\n"); for(i=1;itop;i++) { printf("(%d,%d,%d) ->",s2->ht[i].b1,s2->ht[i].b2,s2->ht[i].id); fprintf(fp,"%c%d%c%d%c%d%c%c",'(',s2->ht[i].b1,',',s2->ht[i].b2,',',s2->ht[i].id,')',' '); if(i==0) fprintf(fp,"%c",'\n'); if(i%7==0) printf("\n"); } fprintf(fp,"%c",'\n'); printf("结束!\n"); printf("(最短路径长度: %d)\n",s2->top); } } void main() //主函数 { char a[T+1]; //二维数组b记录迷宫的每个位置 char filename1[20],filename2[20]; int x1,x2,y1,y2,k; Stack *s1,*s2; direct f1; f1[1].a1=0; f1[1].a2=1; //判断方向(右) f1[2].a1=1; f1[2].a2=0; //(下) f1[3].a1=0; f1[3].a2=-1; //(左) f1[4].a1=-1; f1[4].a2=0; //(上) s1=(Stack *)malloc(sizeof(Stack)); s2=(Stack *)malloc(sizeof(Stack)); s1->top=0; //指向顶(初始化) s2->top=0; create(a); printf("\n\n "); printf("请输入入口坐标: "); scanf("%d%d",&x1,&x2); printf(" "); printf("请输入出口坐标: "); scanf("%d%d",&y1,&y2); printf(" "); printf("请输入存储所有路径的文件名:"); scanf("%s",filename1); printf(" "); printf("请输入存储最短路径的文件名:"); scanf("%s",filename2); system("cls"); k=search(x1,x2,y1,y2,s1,s2,f1,filename1); if(k==1) Print(s2,filename2); printf("\n"); }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值