《数据结构与算法》实验:线性结构及其应用——算术表达式求值

《数据结构与算法》实验和课程Github资源  

《数据结构与算法》实验:线性结构及其应用——算术表达式求值

《数据结构与算法》实验:树型结构的建立与遍历

《数据结构与算法》实验:图结构的建立与搜索

《数据结构与算法》实验:查找结构的实验比较——二叉查找树BST & 二分(折半)查找

《数据结构与算法》实验:排序算法实验比较——选择排序 & 堆排序

《数据结构与算法》实验报告

学生姓名

郭茁宁

院(系)

计算机科学与技术

  

1183710109

 

软件工程

实验时间

2019年11月8 日(周五)

实验地点

格物213室

实验项目

实验1/4:线性结构及其应用

实验目的:将课程的基本原理、技术和方法与实际应用相结合,训练和提高学生组织、存储和处理信息的能力,以及复杂问题的数据结构设计能力和程序设计能力,培养软件设计与开发所需要的实践能力。

实验要求:灵活运用基本的数据结构和算法知识,对实际问题进行分析和抽象;结合程序设计的一般过程和方法为实际问题设计数据结构和有效算法;用高级语言对数据结构和算法进行编程实现、调试,测试其正确性和有效性。

实验题目2/2:算术表达式求值

一个算术表达式是由操作数(operand)、运算符(operator)和界限符(delimiter)组成的。假设操作数是正整数,运算符只含加减乘除等四种运算符,界限符有左右括号和表达式起始、结束符“#”,如:#(7+15)*(23-28/4)#。引入表达式起始、结束符是为了方便。设计一个程序,演示用算符优先法对算术表达式求值的过程。

  1. 从文本文件输入任意一个语法正确的中缀表达式,显示并保存该表达式。
  2. 利用栈结构,把上述中缀表达式转换成后缀表达式,显示栈的状态变化过程和所得到的后缀表达式。
  3. 利用栈结构,对2)形成的后缀表达式进行求值,显示栈的状态变化过程和最终结果。
  4. 将操作数类型扩充到实数、扩充运算符集合,并引入变量操作数,来完成表达式求值。

数据结构定义:

Class Stack:栈

lv:运算符等级字典

vals:变量等级字典

算法设计与分析(要求画出核心内容的程序流程图):

流程图:

问题分为以下三个子问题:

  1. 处理字符串:需要将字符串分解成多个子元素,包括数字、括号、运算符。其中括号和运算符都是单个字符,只要加上单个字符判断即可;数字则可能是带小数点的多位实数,我将小数点’.’也认为是数字,也就是说,每次检测到非括号且非运算符的情况,截取字符均为’0123456789.’中之一最大子串,转换为实数类型存储在列表中。最后得到一个包括数字、括号、运算符的列表。例如:['5.0', '*', '(', '1.2', '-', '6.3', ')', '/', '3.4', '+', '(', '1.6', '-', '0.8', ')', '*', '3.2']
  2. 转换表达式:表达式被拆分后,用新的列表str_list来进行中缀表达式到后缀表达式的转换。首先将符号的等级数字化,例如:lv={'(':5,')':0,'#':1,'+':2,'-':2,'*':3,'/':3,'^':4},然后进行入栈出栈操作:列表指针指向的元素若为数字则不入栈,直接存入ans_str作为答案,若为运算符或括号则通过有限次出栈操作保持栈内符号等级严格单调上升,出栈元素依次加入答案,再把当前元素入栈,并清洗原栈。
  3. 计算值:后缀表达式的列表中,转化为一个双向队列,从队头往队尾遍历,若队头指针指向的是运算符,则从队头出队两个元素,并依据运算符类型进行计算后得出值再从队头入队,最后将指针后移,循环操作。队空是,队尾指针指向的元素即为最后答案。

 

插入附加功能:

  1. 扩展实数集:将小数点纳入数字范围,在“处理字符串”环节中进行判断更改即可;并在列表存储时用实数类型存储、运算,输出保留两位小数。
  2. 引入运算符:我的程序引入指数‘^’运算符,指数运算优先于乘除,所以我将其等级标记为4。在“处理字符串”和环节时判断,之后就能与其他运算符操作大同小异,不必额外讨论。
  3. 设置自变量:我的程序支持根据现代变量命名标准的变量名,即第一个字符为字母,第二个字符及以后支持下划线和数字。此外,设置vals字典用于查询重复变量(避免重复输入数值),要求用户在交互界面依次输入变量的值(支持实数),在“处理字符串”和“转换表达式”环节加入元素首字符识别,在“计算值”环节把自变量代入数值来进行求值。

实验测试结果及结果分析:

测试结果:全对,非常稳定,不惧怕任何强数据

结果分析:每个数据,首先输出预处理的列表,再输出中缀表达式,然后若有自变量则要求用户输入值,最后计算答案

问题及解决方法:

我已流畅解决实验要求,没有问题,具体解决方案详见上文。现对实验测试数据提出问题:

  1. 题目中“引入实数集”没有在测试中体现,测试数据中都是整数;
  2. 题目中“引入运算符号”也没有在数据中体现,我的程序中引入了指数’^’运算符;
  3. 题目中“引入自变量”,数据不够完善,不能检测一些错误,包括:未处理变量重复出现引发的错误、变量名不仅仅只是一个字母;

源程序名称:Lab-1.2.py

注意:正文文字为宋体小4号,图中文字为宋体5号。行距为多倍行距1.25。

      源程序与此报告打包提交,压缩包采用学号命名。

import os
class Stack(object):
    def __init__(self): self.stack=[]
    def push(self,val): self.stack.append(val)
    def pop(self):
        if (not self.empty()): return self.stack.pop()
    def empty(self): return bool(not self.stack)
    def top(self):
        if (not self.empty()): return self.stack[-1]

NUM='0123456789.'
ops='+-*/^'
lv={'(':5,')':0,'#':1,'+':2,'-':2,'*':3,'/':3,'^':4}
chs=[chr(i) for i in range(97,123)]
vals={}

def Shift(str_list):
    sta=Stack()
    ans_str=[]
    for x in str_list:
        if (x[0] in NUM or x[0] in chs):
            ans_str.append(x)
        else:
            while (not sta.empty() and (sta.top() in ops) and lv[x]<=lv[sta.top()]):
                ans_str.append(sta.pop())
                if (ans_str[-1] in '()#'): ans_str.pop()
            sta.push(x)
            if (x!='('):
                while (not sta.empty() and (sta.top() not in ops)): sta.pop()
    while (not sta.empty()):
        ans_str.append(sta.pop())
        if (ans_str[-1] in '()#'): ans_str.pop()
    return ans_str

def op(x2,x1,op):
    if   (op=='+'): return x1+x2
    elif (op=='-'): return x1-x2
    elif (op=='*'): return x1*x2
    elif (op=='/'): return x1/x2
    elif (op=='^'): return x1**x2

def Calc(shift_list):
    ans_num=[]
    for x in shift_list:
        if (x in ops):
            ans_num.append(op(ans_num.pop(),ans_num.pop(),x))
        else:
            if (x[0] in chs):
                ans_num.append(float(vals[x]))
            else:
                ans_num.append(float(x))
    return round(ans_num[0],2)

fin=open("D:\\GZN\\HIT\\个人文件\\数据结构与算法\\Lab1\\test.txt","r")
for str1 in fin:
    s=str1.strip()
    str_list=[]
    s_len=len(s)
    i=0
    j=1
    while (i<=j and j<s_len):
        while (s[j] in NUM or (s[j] not in ops and s[j] not in lv.keys())): j+=1
        str_list.append(s[i:i+1])
        if (i+1<j): str_list.append(s[i+1:j])
        i=j
        j+=1
    for x in str_list:
        if (x=='#'): str_list.remove(x)
    print (str_list)
    shift_list=Shift(str_list)
    print (' '.join(shift_list))
    
    vals.clear()
    for item in shift_list:
        if (item[0] not in NUM and item[0] not in lv.keys() and item not in vals.keys()):
            print (item+'=',end='')
            vals[item]=input()
    print (' '.join(str_list),'=',Calc(shift_list))
    os.system("pause")
发布了36 篇原创文章 · 获赞 11 · 访问量 3538

猜你喜欢

转载自blog.csdn.net/gzn00417/article/details/104145478
今日推荐