数据结构迷宫问题(链式栈)

链式栈结构的实现

思路:

使用链式栈存储可通过的路径;

若当前结点已经走过上下左右四个方向仍不可通行,则把这个点弹出;

具体迷宫实现是课本的函数例子。
在这里插入图片描述

在这里插入图片描述

代码部分

#include<string>
#include<iostream>

using namespace std;

#define OK 1
#define ERROR 0
typedef int SElemType;
typedef int Status;

typedef struct//迷宫
{
	int x;
	int y;
}PosType;

typedef struct {//使用结构体存储栈中元素
	int ord;//通道块在路径中的序号
	PosType seat;//通道块在迷宫中的“座标位置”
	int di;//从此通道块走向下一通道块的“方向”
}MazeNode;

typedef struct SNode {//链式存储栈结点
	MazeNode data;
	struct SNode* next;
}StackNode;

typedef struct LStack//链式栈结构
{
	StackNode *top;
	StackNode *bottom;//定义栈底,却不对栈底进行操作
	int size;
}LinkStack;

int Maze[10][10] = {  //定义迷宫
{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,0,0,1},
{1,0,0,0,0,1,1,0,1,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}
};

LinkStack InitStack(LinkStack s)//栈初始化
{
	s.top = s.bottom = NULL;
	s.size = 0;
	return s;
}

int StackEmpty(LinkStack s)//判断栈是否为空
{
	if (s.top == NULL && s.bottom == NULL)
	{
		return ERROR;
	}
	else
	{
		return OK;
	}
}

LinkStack push(LinkStack s, MazeNode x)//进栈操作
{
	StackNode *t = (StackNode *)malloc(sizeof(StackNode));
	if (t == NULL)
		return s;
	if (StackEmpty(s) == ERROR)
	{
		s.top = s.bottom = t;
		t->next = NULL;
		s.top->data = x;
		printf("(%d,%d)\n", s.top->data.seat.x, s.top->data.seat.y);
		s.size++;
		printf("%d\n", s.size);
		return s;
	}
	else
	{
		t->next = s.top;//续上原来的栈顶
		s.top = t;
		s.top->data = x;
		s.size++;
		return s;

	}
}

LinkStack pop(LinkStack s)//出栈操作
{
	StackNode *t;
	MazeNode q;
	if (StackEmpty(s) == ERROR)
	{
		printf("栈为空,无法进行出栈操作\n");
		return s;
	}
	if (s.top == s.bottom)//出栈元素为栈底元素
	{
		q = s.top->data;
		printf("出栈元素为(%d,%d)\n", q.seat.x, q.seat.y);
		free(s.top);
		s.top = s.bottom = NULL;
		s.size--;
		return s;
	}
	else
	{
		q = s.top->data;
		printf("出栈元素为(%d,%d)\n", q.seat.x, q.seat.y);
		t = s.top->next;
		free(s.top);
		s.top = t;
		s.size--;
		return s;
	}
}

void PrintAll(LinkStack s)//输出所有栈中元素
{
	if (StackEmpty(s) == ERROR)
	{
		printf("此栈为空栈!\n");
	}
	printf("栈中元素为:");
	while (s.top != NULL)
	{
		printf("(%d,%d)\n", s.top->data.seat.x, s.top->data.seat.y);
		s.top = s.top->next;
	}
}

LinkStack DeleteStack(LinkStack s)//销毁栈
{
	StackNode *t;
	while (s.top != NULL)
	{
		t = s.top->next;
		free(s.top);
		s.top = t;
	}
	return s;
}



bool pass(PosType postion)//判断是否可以通过
{
	if (Maze[postion.x][postion.y] == 0)
	{
		return true;
	}
	else
	{
		return false;
	}
}

PosType NextPos(PosType now, int dirction)//转向函数
{
	PosType next;
	switch (dirction)
	{
	case 1:
	{
		next.x = now.x;
		next.y = now.y + 1;
		printf("向右走~\n");
		break;
	}
	case 2:
	{
		next.x = now.x + 1;
		next.y = now.y;
		printf("向下走~\n");
		break;
	}
	case 3:
	{
		next.x = now.x;
		next.y = now.y - 1;
		printf("向左走~\n");
		break;
	}
	case 4:
	{
		next.x = now.x - 1;
		next.y = now.y;
		printf("向上走~\n");
		break;
	}
	default:
		break;
	}
	return next;
}

void footprint(PosType p,int step)
{
	Maze[p.x][p.y] =4;//走过且走通的点标记为4
	printf("走过~");
}

void Markprint(PosType p)
{
	Maze[p.x][p.y] = -1;//走过且走不通的点退栈,标记为0
}


int main()
{
	printf("输出预设迷宫矩阵:\n");
	for (int i = 0; i < 10; i++)
	{
		for (int j = 0; j < 10; j++)
		{
			if (Maze[i][j] == 0)
			{
				printf("O\t");//走通路径
			}
			else
			{
				printf("#\t");//墙壁
			}
		}
		printf("\n");
	}
	LinkStack path;
	path.size = 0;
	path = InitStack(path);//栈初始化
	PosType curpose;
	curpose.x = 1;
	curpose.y = 1;
	int curstep = 1;//步数
	do
	{
		if (pass(curpose))//模仿课本程序
		{
			footprint(curpose,curstep);
			MazeNode e;
			e.di = 1;
			e.ord = curstep;
			e.seat.x = curpose.x;
			e.seat.y = curpose.y;
			path = push(path, e);
			if (curpose.x == 8 && curpose.y == 8)break;
			curpose = NextPos(curpose,e.di);
			curstep++;
		}
		else
		{                                 //这里课本错误,不应该直接pop,因为这时候curpose根本没有入栈
			if (StackEmpty(path) == OK)
			{
				MazeNode e=path.top->data;
				while (StackEmpty(path) == OK && path.top->data.di == 4)
				{
					path = pop(path);
					Markprint(path.top->data.seat);
					printf("栈顶元素为:(%d,%d)", path.top->data.seat.x, path.top->data.seat.y);
					curstep--;
					//break;
				}
				footprint(path.top->data.seat, curstep);
				if (path.top->data.di < 4)
				{
					curpose = NextPos(path.top->data.seat, path.top->data.di + 1);
					path.top->data.di++;
					curstep++;
					path=push(path, path.top->data);
				}
			}
		}

	} while (StackEmpty(path) == OK);
	printf("\n");
	printf("输出迷宫可走通路径:\n");
	for (int i = 0; i < 10; i++)               //输出迷宫结果
	{
		for (int j = 0; j < 10; j++)
		{
			if (Maze[i][j] == 4)
			{
				printf("√\t");//走通路径
			}
			else if (Maze[i][j] == -1)
			{
				printf("×\t");//未走通路径
			}
			else
			{
				printf("#\t");//墙壁
			}
		}
		printf("\n");
	}
	system("PAUSE");
	return 0;
}

运行结果

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

问题与反思

定义栈结构时,由于data又是一个mazenode栈,可以说栈又嵌套了栈,为函数外部的赋值造成了困难。以后要尽量避免。如果需要栈嵌套,函数最好使用指针传参,否则函数内部的值传不出去。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章