數據結構迷宮問題(鏈式棧)

鏈式棧結構的實現

思路:

使用鏈式棧存儲可通過的路徑;

若當前結點已經走過上下左右四個方向仍不可通行,則把這個點彈出;

具體迷宮實現是課本的函數例子。
在這裏插入圖片描述

在這裏插入圖片描述

代碼部分

#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棧,可以說棧又嵌套了棧,爲函數外部的賦值造成了困難。以後要儘量避免。如果需要棧嵌套,函數最好使用指針傳參,否則函數內部的值傳不出去。

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