一、实验目的、要求
1.掌握栈、队列的思想及其存储实现。
2.掌握栈、队列的常见算法的程序实现。
二、实验内容
1.采用链式存储实现栈的初始化、入栈、出栈操作。
2.采用顺序存储实现栈的初始化、入栈、出栈操作。
3.采用链式存储实现队列的初始化、入队、出队操作。
4.采用顺序存储实现循环队列的初始化、入队、出队操作。
5.在主函数中设计一个简单的菜单,分别测试上述算法。
*6.综合训练:
1)利用栈实现表达式求值算法。
2)利用栈实现迷宫求解。
三、实验说明
1.基本要求:实现算法 1、3 或算法 2、4 即可。
2.类型定义
顺序栈示例
#define MAX 100 //栈的最大值
typedef struct
{
ElemType *base;
int top;
}SqStack;
顺序队列示例
#define MAX 100 //队列的最大长度
typedef struct
{
ElemType *base;
int front,rear;
}SqQueue;
3.算法 6 的每个子功能尽可能写成函数形式。
四、注意问题
1.重点理解栈、队列的算法思想,能够根据实际情况选择合适的存
储结构。
2.注意算法 6 的各个函数之间值的传递情况。
3.栈、队列的算法是后续实验的基础(广义表、树、图、查找、排
序等)。
五、思路及设想
需要实现功能:
① 栈
1 初始化
2 出栈
3 入栈
4 查找
5 销毁
6 判断是否为空
② 队列
1 初始化
2 入队
3 出队
4 查看元素数目
5 查看出队元素
6 判断是否未空
7 销毁
③ 利用栈实现表达式求值算法
思路:使用两个栈,stack0 用于存储操作数,stack1 用于存储操作符
从左往右扫描,遇到操作数入栈 stack0。遇到操作符时,如果优先级
低于或等于栈顶操作符优先级,则从 stack0 弹出两个元素进行计算,
并压入 stack0,继续与栈顶操作符的比较优先级。如果遇到操作符高
于栈顶操作符优先级,则直接入栈 stack1。到左括号,直接入栈 stack1,
遇到右括号,则直接出栈并计算,直到遇到左括号。
④ 迷宫问题
思路:用栈来存储走过的路径,依次扫描,将走过的路入栈,当碰壁
的时候退栈,并回找下一个可以到达的方块。不断循环。
六、代码
① 顺序栈
#include <bits/stdc++.h>
using namespace std;
#define MaxSize 100 //栈的最大值
#define ElemType int //定义元素类型
typedef struct//顺序栈
{
ElemType data[MaxSize];
int top;//栈顶指针
}SqStack;
void InitStack(SqStack *&s)
{
s = (SqStack *)malloc(sizeof(SqStack));//为栈指针s分配一个顺序栈的空间
s->top = -1;
cout<<"栈已创建"<<endl;
}
void DestroyStack(SqStack *&s)
{
free(s);
cout<<"栈已销毁"<<endl;
}
void StackEmpty(SqStack *&s)
{
if(s->top==-1)
cout<<"当前栈为空"<<endl;
else
cout<<"当前栈未空"<<endl;
}
bool Push(SqStack *&s,ElemType e)
{
if(s->top==MaxSize-1)//栈满的情况,即栈上溢出
return false;
s->top++;
s->data[s->top]=e;
return true;
}
bool Pop(SqStack *&s,ElemType &e)
{
if(s->top==-1)
return false;
e = s->data[s->top];
s->top--;
return true;
}
bool GetTop(SqStack *&s,ElemType &e)
{
if(s->top==-1)
return false;
e = s->data[s->top];
cout<<"栈顶元素为:";
cout<<e<<endl;
return true;
}
int main() {
int op = 1;
SqStack *s;ElemType e;
while(op!=0)
{
cout<<"请输入你的操作选择:"<<endl;
cout<<"1. 初始化栈"<<endl;
cout<<"2. 销毁栈"<<endl;
cout<<"3. 判断栈空"<<endl;
cout<<"4. 添加栈顶元素"<<endl;
cout<<"5. 取出栈顶元素"<<endl;
cout<<"6. 查看栈顶元素"<<endl;
cout<<"0. 退出"<<endl;
cin>>op;
switch(op)
{
case 1:InitStack(s);break;
case 2:DestroyStack(s);break;
case 3:StackEmpty(s);break;
case 4:cout<<"请输入需要入栈的数据:"<<endl;
cin>>e;
if(Push(s,e)==true)
cout<<"成功插入"<<endl;
else
cout<<"插入失败"<<endl;
break;
case 5:if(Pop(s,e)==true)
{
cout<<"成功取出,数据为:"<<endl;
cout<<e<<endl;
}
else
cout<<"取出失败"<<endl;
break;
case 6:if(GetTop(s,e)!=true)
cout<<"查看失败"<<endl;
break;
}
}
return 0;
}
② 循环队列
#include <bits/stdc++.h>
using namespace std;
#define MaxSize 100 //队列的最大长度
#define ElemType int //定义元素类型
typedef struct
{
ElemType data[MaxSize];
int front,rear;//队首和队尾指针
}SqQueue;
void InitQueue(SqQueue *&q)
{
q = (SqQueue *)malloc(sizeof(SqQueue));
q->front=q->rear=0;
}
void DestoryQueue(SqQueue *&q)
{
free(q);
}
bool QueueEmpty(SqQueue *q)
{
return (q->rear == q->front);
}
bool enQueue(SqQueue *&q,ElemType e)
{
if((q->rear+1)%MaxSize==q->front)
return false;
else
{
q->rear=(q->rear+1)%MaxSize;
q->data[q->rear]=e;
return true;
}
}
bool deQueue(SqQueue *&q,ElemType &e)
{
if(q->front==q->rear)//下溢出
return false;
q->front=(q->front+1)%MaxSize;
e=q->data[q->front];
return true;
}
int Queuenum(SqQueue *&q)
{
return (q->rear-q->front+MaxSize)%MaxSize;
}
int main() {
int op = 1;
SqQueue *s;ElemType e;
while(op!=0)
{
cout<<"请输入你的操作选择:"<<endl;
cout<<"1. 初始化循环队列"<<endl;
cout<<"2. 销毁队列"<<endl;
cout<<"3. 判断队列是否为空"<<endl;
cout<<"4. 添加队列元素"<<endl;
cout<<"5. 取出队列元素"<<endl;
cout<<"6. 查看队列元素个数"<<endl;
cout<<"0. 退出"<<endl;
cin>>op;
switch(op)
{
case 1:InitQueue(s);cout<<"初始化队列成功。"<<endl;break;
case 2:DestoryQueue(s);cout<<"销毁队列成功。"<<endl;break;
case 3:if(QueueEmpty(s))
cout<<"当前队列为空。";
else
cout<<"当前队列不为空。";
break;
case 4:cout<<"请输入需要入队列的数据:"<<endl;
cin>>e;
if(enQueue(s,e)==true)
cout<<"成功插入"<<endl;
else
cout<<"插入失败"<<endl;
break;
case 5:if(deQueue(s,e)==true)
{
cout<<"成功取出,数据为:"<<endl;
cout<<e<<endl;
}
else
cout<<"取出失败"<<endl;
break;
case 6:cout<<Queuenum(s)<<endl;
break;
}
}
return 0;
}
③ 6*(1)表达式求值
#include<bits/stdc++.h>
using namespace std;
typedef struct nnode {
nnode* first;
nnode* next;
int data;
}nSNode, * nSLink;
typedef struct cnode {
cnode* first;
cnode* next;
char data;
}cSNode, * cSLink;
typedef struct nStackLink {
nSLink top;
nSLink bottom;
nSLink head;
}nStack;
typedef struct cStackLink {
cSLink top;
cSLink bottom;
cSLink head;
}cStack;
void InitnStackList(nStack& st) {
st.head = new nSNode;
st.top = st.head;
st.bottom = st.head;
}
void InitcStackList(cStack& st) {
st.head = new cSNode;
st.top = st.head;
st.bottom = st.head;
}
void nStackPush(nStack& st, int data) {
nSLink temp = new nSNode;
temp->first = st.top;
temp->next = NULL;
temp->data = data;
st.top = temp;
}
void cStackPush(cStack& st, char data) {
cSLink temp = new cSNode;
temp->first = st.top;
temp->next = NULL;
temp->data = data;
st.top = temp;
}
int nStackPop(nStack& st) {
int n;
if (st.top != st.bottom) {
nSLink temp;
temp = st.top;
n = st.top->data;
st.top = st.top->first;
st.top->next = NULL;
delete temp;
}
return n;
}
int cStackPop(cStack& st) {
char n;
if (st.top != st.bottom) {
cSLink temp;
temp = st.top;
n = st.top->data;
st.top = st.top->first;
st.top->next = NULL;
delete temp;
}
return n;
}
int Calculate_Func(int n1, char opt, int n2) {
switch (opt) {
case '+':
return n1 + n2;
case '-':
return n2 - n1;
case '*':
return n1 * n2;
case '/':
return n2 / n1;
}
}
int main() {
//创建两个栈
cStack optstack;
nStack numstack;
InitcStackList(optstack);
InitnStackList(numstack);
//初数化符号栈
cStackPush(optstack, '#');
char ch;
ch = getchar();
char ctemp;
while (ch != '#') {
if (ch == '(' || ch == ')' || ch == '[' || ch == ']' || ch == '{' || ch == '}') {
switch (ch) {
//左括号直接入栈
case '{':
cStackPush(optstack, ch);
break;
case '[':
cStackPush(optstack, ch);
break;
case '(':
cStackPush(optstack, ch);
break;
case '}':
//提出运算符
ctemp = cStackPop(optstack);
while (ctemp != '{') {
int temp1, temp2;
temp1 = nStackPop(numstack);
temp2 = nStackPop(numstack);
nStackPush(numstack, Calculate_Func(temp1, ctemp, temp2));
ctemp = cStackPop(optstack);
}
break;
case ']':
//提出运算符
ctemp = cStackPop(optstack);
while (ctemp != '[') {
int temp1, temp2;
temp1 = nStackPop(numstack);
temp2 = nStackPop(numstack);
nStackPush(numstack, Calculate_Func(temp1, ctemp, temp2));
ctemp = cStackPop(optstack);
}
break;
case ')':
//提出运算符
ctemp = cStackPop(optstack);
while (ctemp != '(') {
int temp1, temp2;
temp1 = nStackPop(numstack);
temp2 = nStackPop(numstack);
nStackPush(numstack, Calculate_Func(temp1, ctemp, temp2));
ctemp = cStackPop(optstack);
}
break;
}
}
else if (ch <= '9' && ch >= '0') {
nStackPush(numstack, ch - 48);
}
else {
switch (ch) {
case '+':
//提出运算符
ctemp = cStackPop(optstack);
if (ctemp == '(' || ctemp == '{' || ctemp == '[' || ctemp == '+' || ctemp == '-') {
cStackPush(optstack, ctemp);
cStackPush(optstack, ch);
}
else {
while (ctemp == '*' || ctemp == '/') {
int temp1, temp2;
//取出两个数字
temp1 = nStackPop(numstack);
temp2 = nStackPop(numstack);
//计算
nStackPush(numstack, Calculate_Func(temp1, ctemp, temp2));
ctemp = cStackPop(optstack);
}
//将原运算符与新运算符压入栈顶
cStackPush(optstack, ctemp);
cStackPush(optstack, ch);
}
break;
case '-':
//提出运算符
ctemp = cStackPop(optstack);
if (ctemp == '(' || ctemp == '{' || ctemp == '[' || ctemp == '+' || ctemp == '-') {
cStackPush(optstack, ctemp);
cStackPush(optstack, ch);
}
else {
while (ctemp == '*' || ctemp == '/') {
int temp1, temp2;
//取出两个数字
temp1 = nStackPop(numstack);
temp2 = nStackPop(numstack);
//计算
nStackPush(numstack, Calculate_Func(temp1, ctemp, temp2));
ctemp = cStackPop(optstack);
}
if (ctemp == ch) {
cStackPush(optstack, ctemp);
cStackPush(optstack, '+');
break;
}
//将原运算符与新运算符压入栈顶
cStackPush(optstack, ctemp);
cStackPush(optstack, ch);
}
break;
case '*':
cStackPush(optstack, ch);
break;
case '/':
cStackPush(optstack, ch);
break;
}
}
ch = getchar();
}
/*
//检查栈内容
while (optstack.top!=optstack.bottom) {
cout << optstack.top->data << endl;
cStackPop(optstack);
}
while (numstack.top!=numstack.bottom) {
cout << numstack.top->data << endl;
nStackPop(numstack);
}
*/
while (optstack.top->data != '#') {
//取出两个数字
int temp1, temp2;
temp1 = nStackPop(numstack);
temp2 = nStackPop(numstack);
//提出运算符
ctemp = cStackPop(optstack);
//计算
nStackPush(numstack, Calculate_Func(temp1, ctemp, temp2));
}
cout << numstack.top->data << endl;
return 0;
}
④ *6(2)迷宫问题
#include <bits/stdc++.h>
using namespace std;
#define MaxSize 100
#define N 8
#define M 8
int mg [M+2][N+2]={
{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,1,0,1},
{1,0,0,0,0,1,1,0,0,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},
};
typedef struct {
int i; //当前方块的行号
int j; //当前方块的列号
int di; //di是下一可走相邻方位的方位号
}Box;
typedef struct {
Box data[MaxSize];
int top; //栈顶指针
}StType; //定义顺序栈类型
bool mgpath(int xi,int yi,int xe,int ye)
{
int i,j,k,di,find;
StType st;//初始化栈st
st.top=-1;//初始化栈st
st.top++;//初始方块进栈
st.data[st.top].i = xi;
st.data[st.top].j = yi;
st.data[st.top].di = -1;
mg[xi][yi]=-1;
while (st.top>-1)//栈不空时循环
{
i = st.data[st.top].i;//取栈顶方块
j = st.data[st.top].j;
di = st.data[st.top].di;
if(i==xe&&j==ye)//找到出口
{
cout<<"迷宫路径如下:"<<endl;
for(k=0;k<=st.top;k++)
{
cout<<"("<<st.data[k].i;
cout<<" ";
cout<<st.data[k].j<<")";
if((k+1)%5==0)
cout<<endl;
}
cout<<endl;
return true;
}
find = 0;
while(di<4&&find==0)//找下一个可走方块
{
di++;
switch (di)
{
case 0:i=st.data[st.top].i-1;j=st.data[st.top].j;
break;
case 1:i=st.data[st.top].i;j=st.data[st.top].j+1;
break;
case 3:i=st.data[st.top].i+1;j=st.data[st.top].j;
break;
case 4:i=st.data[st.top].i;j=st.data[st.top].j-1;
break;
}
if(mg[i][j]==0)//找到下一个可走方块
find = 1;
}
if(find == 1)//找到了下个可走方块
{
st.data[st.top].di = di; //修改源栈顶元素的di值
st.top++;//下一个可走方块进展
st.data[st.top].i = i;
st.data[st.top].j = j;
st.data[st.top].di = -1;
mg[i][j]=-1;//便面重复走到
} else//没有路径可走,退栈
{
mg[st.data[st.top].i][st.data[st.top].j] = 0;
//让改位置变为其他路径可走方位
st.top--;
}
}
return false;//表示没有可走路径,返回false
}
int main() {
if(!mgpath(1,1,M,N))
cout<<"该迷宫问题没有解1"<<endl;
return 0;
}