鏈式棧結構的實現
思路:
使用鏈式棧存儲可通過的路徑;
若當前結點已經走過上下左右四個方向仍不可通行,則把這個點彈出;
具體迷宮實現是課本的函數例子。
代碼部分
#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棧,可以說棧又嵌套了棧,爲函數外部的賦值造成了困難。以後要儘量避免。如果需要棧嵌套,函數最好使用指針傳參,否則函數內部的值傳不出去。