数据结构实验课:实验三、栈的实现及应用

简介: 数据结构实验课:实验三、栈的实现及应用

一、实验目的


1.掌握栈的存储表示和实现

2.掌握栈的基本操作实现。

3.掌握栈在解决实际问题中的应用。


二、实验要求


问题描述:设计一个程序,演示用算符优先法对算术表达式求值的过程。利用算符优先关系,实现对算术四则混合运算表达式的求值。


(1)输入的形式:表达式,例如2*(3+4)#

包含的运算符只能有’+’ 、’-’ 、’’ 、’/’ 、’(’、 ‘)’,“#”代表输入结束符;

(2)输出的形式:运算结果,例如2(3+4)=14;

(3)程序所能达到的功能:对表达式求值并输出。


三、解题参考思路


为了实现用栈计算算数表达式的值,需设置两个工作栈:用于存储运算符的栈opter,以及用于存储操作数及中间结果的栈opnd。

算法基本思想如下:


(1)首先将操作数栈opnd设为空栈,而将’#‘作为运算符栈opter的栈底元素,这样的目的是判断表达式是否求值完毕。

(2)依次读入表达式的每个字,表达式须以’#‘结,读入字符若是操作数则入栈opnd,读入字符若是运算符,则将此运算符c与opter的栈顶元素top比较优先级后执行相应的操作,具体操作如下:


(i)若top的优先级小于c,即top

(ii)若top的优先级等于c,即top=c,则弹出opter的栈顶元素,并读入下一字符赋值给c,这一步目的是进行括号操作;

(iii)若top优先级高于c,即top>c,则表明可以计算,此时弹出opnd的栈顶两个元素,并且弹出opter栈顶的的运算符,计算后将结果放入栈opnd中。直至opter的栈顶元素和当前读入的字符均为’#’,此时求值结束。

算符间的优先关系如下表所示(表来源:严蔚敏《数据结构》):


表中需要注意的是θ1为opter的栈顶元素,θ2为从表达式中读取的操作符,此优先级表可以用二维数组实现。

图例:


比较算符优先关系代码示例:


int getIndex(char theta) //获取theta所对应的索引
{
int index = 0;
switch (theta)
{
case ‘+’:
index = 0;
break;
case ‘-’:
index = 1;
break;
case ‘*’:
index = 2;
break;
case ‘/’:
index = 3;
break;
case ‘(’:
index = 4;
break;
case ‘)’:
index = 5;
break;
case ‘#’:
index = 6;
default:break;
}
return index;
}
char getPriority(char theta1, char theta2) //获取theta1与theta2之间的优先级
{
const char priority[][7] = //算符间的优先级关系
{
{ ‘>’,’>’,’<’,’<’,’<’,’>’,’>’ },
{ ‘>’,’>’,’<’,’<’,’<’,’>’,’>’ },
{ ‘>’,’>’,’>’,’>’,’<’,’>’,’>’ },
{ ‘>’,’>’,’>’,’>’,’<’,’>’,’>’ },
{ ‘<’,’<’,’<’,’<’,’<’,’=’,‘0’ },
{ ‘>’,’>’,’>’,’>’,‘0’,’>’,’>’ },
{ ‘<’,’<’,’<’,’<’,’<’,‘0’,’=’ },
};
int index1 = getIndex(theta1);
int index2 = getIndex(theta2);
return priority[index1][index2];
}
————————————————
版权声明:本文为CSDN博主「superlistboy」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_51222650/article/details/117048535


四、实验任务


认真阅读与理解实验内容的具体要求,参考教材相关章节,结合实验内容的要求,编写实验程序并上机调试与测试,完成实验报告的撰写。


(已改)代码如下


#include <stdio.h>
#include <stdlib.h>
#define OK 1
#define ERROR 0
#define MAXSIZE 100 // 存储空间初始分配量
typedef int Status;
typedef struct
{
        int data[MAXSIZE];
        int top; // 用于栈顶指针
}opndStack;
typedef struct
{
        char data[MAXSIZE];
        int top; // 用于栈顶指针
}opterStack;
//====================================================================
int getIndex(char theta)   //获取theta所对应的索引
{
    int index = 0;
    switch (theta)
    {
      case '+':
          index = 0;
          break;
      case '-':
          index = 1;
          break;
      case '*':
          index = 2;
          break;
      case '/':
          index = 3;
          break;
      case '(':
          index = 4;
          break;
      case ')':
          index = 5;
          break;
      case '#':
          index = 6;
      default:break;
    }
    return index;
}
//====================================================================
char getPriority(char theta1, char theta2)   //获取theta1与theta2之间的优先级
{
    const char priority[][7] =     //算符间的优先级关系
    {
        { '>','>','<','<','<','>','>' },
        { '>','>','<','<','<','>','>' },
        { '>','>','>','>','<','>','>' },
        { '>','>','>','>','<','>','>' },
        { '<','<','<','<','<','=','0' },
        { '>','>','>','>','0','>','>' },
        { '<','<','<','<','<','0','=' },
    };
    int index1 = getIndex(theta1);
    int index2 = getIndex(theta2);
    return priority[index1][index2];
}
//====================================================================
Status InitopndStack(opndStack *S)//建立opnd空栈
{
    S->top=-1;
    return OK;
}
Status InitopterStack(opterStack *S)//建立opter空栈
{
    S->top=-1;
    return OK;
}
//====================================================================
Status Pushnd(opndStack *S,int n)//入栈
{
    if(S->top== MAXSIZE-1)
    {
        return ERROR;
    }
    S->top++;//
    S->data[S->top]=n;
    return OK;
}
Status Pushter(opterStack *S,char n)
{
    if(S->top== MAXSIZE-1)
    {
        return ERROR;
    }
    S->top++;//
    S->data[S->top]=n;
    return OK;
}
//=========================================================
Status Popnd(opndStack *S,int *n)//出栈 并返回到 n 中
{
    if(S->top==-1)
        return ERROR;
    *n=S->data[S->top];
    (S->top)--;
    return OK;
}
Status Popter(opterStack *S,char *n)
{
    if(S->top==-1)
        return ERROR;
    *n=S->data[S->top];
    S->top--;
    return OK;
}
//=======================================================
signed int calculate(int x1,int x2,char c)
{
    switch(c)
    {
    case '+':
        return (x1+x2);
    case '-':
        return (x1-x2);
    case '*':
        return (x1)*(x2);
    case '/':
        return (x1)/(x2);
    default:
        return 0;
    }
    return 0;
}
//======================================================
int isdigit(char c)//判断是否为操作数
{
    if(c<='9'&& c>='0')
        return 1;
    else
        return 0;
}
int ischar(char c)//判断是否为运算符
{
    switch(c)
    {
    case '+':
    case '-':
    case '*':
    case '/':
    case '(':
    case ')':
    case '#':
        return 1;
    default:
        return 0;
    }
    return 0;
}
//=========================================================
void input(char s[])  //输入表达式 存入s[]数组中。
{
    char c;
    int i = 0;
    while(c!='#')
    {
        while((c=getchar())==' ');//跳过所有空格进行c的输入
        s[i++]=c;
    }
    return ;
}
//==========================================================
int calculateall()
{
    char c,s[100]={0},k;
    int x1,x2,i=0;
    int n=0;
    opndStack opnd;
    opterStack opter;
    InitopndStack(&opnd); //空栈
    InitopterStack(&opter);
    Pushter(&opter,'#');
    input(s);
    while(s[i]!='\0')
    {
        c=s[i];
            if(ischar(c))
            {
                 switch(getPriority(opter.data[opter.top],c))
                    {
                    case '<':
                        Pushter(&opter,c);
                        break;
                    case '=':
                        Popter(&opter,&k);//k没有用处 用来满足函数关系而已
                        break;
                    case '>':
                        while(getPriority(opter.data[opter.top],c)=='>')
                        {
                            Popnd(&opnd,&x1);
                            Popnd(&opnd,&x2);
                            Popter(&opter,&k);
                            x1=calculate(x2,x1,k);
                            Pushnd(&opnd,x1);
                        }
                        if(getPriority(opter.data[opter.top],c)=='<')
                            Pushter(&opter,c);
                        else
                            Popter(&opter,&k);
                        break;
                    default:
                        printf("INPUT ERROR");
                    }
            }
            else
            {
                Pushnd(&opnd,c-'0');
            }
        ++i;
    }
    Popnd(&opnd,&k);
    return k;
}
//=========================================================
int main()
{
   int k;
   k=calculateall();
   printf("%d",k);
   return 0;
}


当时自己写的版本(c++)


#include <iostream>
using namespace std;
#include <string>
#define size2 10
#define size1 100
#define erro -1
typedef int iii;
typedef struct
{
    char *base;
    char *top;
    int size;
} stack2;
typedef struct
{
    iii * base;
    iii* top;
    int size;
} stack;
void InitStack(stack2 &s)//初始化栈
{
    s.base=(char*)malloc (size1*sizeof(char));
    if(!s.base)
    {
        printf("超出界限\n");
        return;
    }
    else
    {
        s.top=s.base;
        s.size=size1;
    }
}
void InitStack(stack &s)//初始化栈
{
    s.base=(iii *)malloc (size1*sizeof(iii));
    if(!s.base)
    {
        printf("超出界限\n");
        return;
    }
    else
    {
        s.top=s.base;
        s.size=size1;
    }
}
void Insert(stack2 &s,char a) //插入元素
{
    if(s.top-s.base>=s.size)
    {
        s.base=(char *)realloc (s.base,(s.size+size1)*sizeof (char));
        if(!s.base)
        {
            printf("超出界限\n");
            return ;
        }
    }
    *s.top++=a;
}
void Insert2( stack &s,int a)
{
    if(s.top-s.base>=s.size)
    {
        s.base=(iii *)realloc (s.base,(s.size+size1)*sizeof (iii));
        if(!s.base)
        {
            printf("超出界限\n");
            return ;
        }
    }
    *s.top++=a;
}
char Pop(stack2 &s )//删除栈顶元素,并返回栈顶元素
{
    if(s.top==s.base)
    {
        printf("栈为空\n");
        return erro;
    }
    else
    {
        *--s.top;
        return * s.top;
    }
}
int Pop2(stack &s)
{
    if(s.top==s.base)
    {
        printf("栈为空\n");
        return erro;//没意义
    }
    else
    {
        *--s.top;
        return * s.top;
    }
}
void View(stack &s)
{
    for(int i=1; i<=(s.top-s.base); i++)
    {
        char k;
        k=*(s.top-i);
        cout<<k<<endl;
    }
}
char GetPop(stack2 &s)
{
    if(s.top==s.base)
    {
        printf("栈为空\n");
        return-1;
    }
    else
        return *(s.top-1);
}
int GetPop2(stack &s)
{
    if(s.top==s.base)
    {
        printf("栈为空\n");
        return-1;
    }
    else
        return *(s.top-1);
}
char Compare(char q,char r)//比较优先级
{
    int j[2];
    char str[2];
    char table[7][7]=
    {
        {'>','>','<','<','<','>','>'},
        {'>','>','<','<','<','>','>'},
        {'>','>','>','>','<','>','>'},
        {'>','>','>','>','<','>','>'},
        {'<','<','<','<','<','=','e'},
        {'>','>','>','>','e','>','>'},
        {'<','<','<','<','<','e','='}
    };
    str[0]=q;
    str[1]=r;
    for(int i=0; i<2; i++)
    {
        switch(str[i])
        {
        case '+':
            j[i]=0;
            break;
        case '-':
            j[i]=1;
            break;
        case '*':
            j[i]=2;
            break;
        case '/':
            j[i]=3;
            break;
        case '(':
            j[i]=4;
            break;
        case ')':
            j[i]=5;
            break;
        case '#':
            j[i]=6;
            break;
        }
    }
    return table[j[0]][j[1]];
}
int Operate (int a,char b,int c)
{
    switch(b)
    {
    case '+':
        return a+c;
    case '-':
        return a-c;
    case '*':
        return a*c;
    case '/':
        return a/c;
    }
}
bool Decide(char c)
{
    if(c=='+'||c=='-'||c=='*'||c=='/'||c=='('||c==')'||c=='#')
        return true;
    else
        return false;
}
int main()
{
    stack2 a;
    stack b;//a存储符号,b存储数字
    InitStack(a);
    Insert(a,'#');
    InitStack(b);
    char c;
    c=getchar();
    int temp=0;
    while (c!='#'||GetPop(a)!='#')
    {
        if(!Decide(c))
        {
            temp=(temp*10+c-'0');//可支持数位数字
            c=getchar();
        }
        else if(Decide(c))
        {
            if(temp!=0)
            {
                Insert2(b,temp);
            }
            temp=0;
            switch(Compare(GetPop(a),c))
            {
            case '<':
//栈顶元素优先权低
//cout<<"<"<<endl;
                Insert(a,c);
                c=getchar();
                break;
            case '=':
//脱括号
                Pop(a);
                c=getchar();
                break;
            case'>':
                char f=Pop(a);
                int g=Pop2(b);
                int h=Pop2(b);
                Insert2(b,Operate(h,f,g));
                break;
            }
        }
    }
    cout<<"结果为"<<endl;
    cout<<GetPop2(b)<<endl;
    return 0;
}


相关文章
|
27天前
|
C语言
【数据结构】栈和队列(c语言实现)(附源码)
本文介绍了栈和队列两种数据结构。栈是一种只能在一端进行插入和删除操作的线性表,遵循“先进后出”原则;队列则在一端插入、另一端删除,遵循“先进先出”原则。文章详细讲解了栈和队列的结构定义、方法声明及实现,并提供了完整的代码示例。栈和队列在实际应用中非常广泛,如二叉树的层序遍历和快速排序的非递归实现等。
123 9
|
18天前
|
存储 算法
非递归实现后序遍历时,如何避免栈溢出?
后序遍历的递归实现和非递归实现各有优缺点,在实际应用中需要根据具体的问题需求、二叉树的特点以及性能和空间的限制等因素来选择合适的实现方式。
23 1
|
6天前
|
存储 缓存 算法
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式,强调了合理选择数据结构的重要性,并通过案例分析展示了其在实际项目中的应用,旨在帮助读者提升编程能力。
28 5
|
21天前
|
存储 算法 Java
数据结构的栈
栈作为一种简单而高效的数据结构,在计算机科学和软件开发中有着广泛的应用。通过合理地使用栈,可以有效地解决许多与数据存储和操作相关的问题。
|
24天前
|
存储 JavaScript 前端开发
执行上下文和执行栈
执行上下文是JavaScript运行代码时的环境,每个执行上下文都有自己的变量对象、作用域链和this值。执行栈用于管理函数调用,每当调用一个函数,就会在栈中添加一个新的执行上下文。
|
26天前
|
存储
系统调用处理程序在内核栈中保存了哪些上下文信息?
【10月更文挑战第29天】系统调用处理程序在内核栈中保存的这些上下文信息对于保证系统调用的正确执行和用户程序的正常恢复至关重要。通过准确地保存和恢复这些信息,操作系统能够实现用户模式和内核模式之间的无缝切换,为用户程序提供稳定、可靠的系统服务。
47 4
|
1月前
|
算法 安全 NoSQL
2024重生之回溯数据结构与算法系列学习之栈和队列精题汇总(10)【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丢脸好嘛?】
数据结构王道第3章之IKUN和I原达人之数据结构与算法系列学习栈与队列精题详解、数据结构、C++、排序算法、java、动态规划你个小黑子;这都学不会;能不能不要给我家鸽鸽丢脸啊~除了会黑我家鸽鸽还会干嘛?!!!
|
2月前
|
算法 程序员 索引
数据结构与算法学习七:栈、数组模拟栈、单链表模拟栈、栈应用实例 实现 综合计算器
栈的基本概念、应用场景以及如何使用数组和单链表模拟栈,并展示了如何利用栈和中缀表达式实现一个综合计算器。
34 1
数据结构与算法学习七:栈、数组模拟栈、单链表模拟栈、栈应用实例 实现 综合计算器
|
2月前
初步认识栈和队列
初步认识栈和队列
61 10
|
2月前
数据结构(栈与列队)
数据结构(栈与列队)
20 1