数据结构与算法实验 ——(二)实验二 栈的设计、实现及应用

一、实验目的、要求

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;
}

  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值