利用栈求表达式的值
数据结构-表达式求值
![数据结构-表达式求值](https://img.taocdn.com/s3/m/55d2d078f46527d3240ce049.png)
数据结构:线性结构—栈实现表达式求值一.问题分析利用栈这种数据结构存储数字和运算符,并实现表达式求值。
为实现按运算符优先顺序进行计算,需要在执行程序的过程中对运算符的优先顺序做出判断。
利用栈先进后出的特点,同时保证优先级最高的运算符始终在栈顶。
当栈顶元素优先级低于读入的运算符时,将该栈顶运算符推出。
这就保证了优先级高的运算符先计算。
二.数据结构—栈1.优先关系表:prior[7][7]={// +-*/()#'>','>','<','<','<','>','>','>','>','<','<','<','>','>','>','>','>','>','<','>','>','>','>','>','>','<','>','>','<','<','<','<','<','=',' ','>','>','<','>',' ','>','>','<','<','<','<','<',' ','='};将关系表直接用字符型的二维数组存储。
计算机408统考真题
![计算机408统考真题](https://img.taocdn.com/s3/m/a90512d308a1284ac85043e2.png)
计算机专业基础综合考试模拟试卷(一)一、单项选择题:第1~40小题,每小题2分,共80分。
下列每题给出的四个选项中,只有一个选项最符合试题要求。
1.已知一个栈的进栈序列是1、2、3、…、n,其输出序列为p1、p2、p3、…、p n,若p1=3,则p2为()。
A.2或4、5、…、n都有可能B.可能是1C.一定是2 D.只可能是2或4 2.利用栈求表达式的值时,设立运算数栈OPEN。
假设OPEN只有两个存储单元,则在下列表达式中,不会发生溢出的是()。
A.A−B*(C−D) B.(A−B)*C−D C.(A−B*C)−DD.(A−B)*(C−D)3.已知A[1…N]是一棵顺序存储的完全二叉树,9号结点和11号结点共同的祖先是()。
A.4 B.6 C.2D.84.在常用的描述二叉排序树的存储结构中,关键字值最大的结点是()。
A.左指针一定为空B.右指针一定为空C.左、右指针均为空D.左、右指针均不为空5.分别以下列序列构造二叉排序树,与用其他三个序列所构造的结果不同的是()。
A.(100,80, 90,60,120,110,130)B.(100,120,110,130,80,60,90)C.(100,60,80,90,120,110,130)D.(100,80, 60,90,120,130,110)6.设无向图G=(V,E)和G′=(V′,E′),如果G′是G的生成树,则下面说法错误的是()。
A.G′是G的子图B.G′是G的连通分量C.G′是G的极小连通子图且V=V′D.G′是G的一个无环子图7.若G是一个具有36条边的非连通无向简单图,则图G的结点数至少是()。
A.11 B.10 C.9D.88.在有向图G的拓扑序列中,若顶点V i在顶点V j之前,则下列情形不可能出现的是()。
A.G中有弧<V i,V j> B.G中有一条从V i到V j的路径C.G中没有弧< V i,V j> D.G中有一条从V j到V i的路径9.具有12个关键字的有序表中,对每个关键字的查找概率相同,折半查找查找成功和查找失败的平均查找长度依次为()。
基于栈的后缀算术表达式求值c语言
![基于栈的后缀算术表达式求值c语言](https://img.taocdn.com/s3/m/786b1c8e9fc3d5bbfd0a79563c1ec5da50e2d6e6.png)
基于栈的后缀算术表达式求值c语言1. 引言1.1 概述本文将讨论基于栈的后缀算术表达式求值的实现过程。
后缀算术表达式(也称为逆波兰表达式)是一种无需括号即可进行运算的表达式表示方法,它将操作符置于操作数之后。
相较于传统的中缀表达式,在计算机程序中处理后缀表达式更为高效和简洁。
1.2 文章结构文章分为五个主要部分:引言、栈的概念及原理、后缀算术表达式的定义和转换、基于栈的后缀算术表达式求值算法实现以及结论与总结。
在引言部分,我们将首先介绍本文的概述和目标,对后续内容进行简要说明。
1.3 目的通过本文,我们旨在让读者了解栈数据结构的基本概念和原理,并且掌握如何利用栈来实现对后缀算术表达式进行求值的算法。
同时,我们将介绍后缀算术表达式的定义和转换方法,并给出基于栈实现该计算方式的详细步骤与示例代码。
通过深入研究并学习这些内容,读者可以加深对栈数据结构和后缀算术表达式的理解,并且能够应用所学知识解决实际问题。
本文不仅适用于计算机科学或相关专业的学生,也适合对数据结构和算法感兴趣的读者阅读和学习。
2. 栈的概念及原理2.1 栈的定义栈是一种具有特定限制条件的线性数据结构,它具备“先进后出”(Last-In-First-Out,LIFO)的特性。
栈可以看作是一个容器,其中可以存储各种类型的数据。
与实际生活中的堆栈类似,栈只允许在其末尾进行插入和删除操作。
在栈中,最后加入的元素首先被访问和处理。
这是由于栈内元素之间的相对位置关系决定的。
插入操作称为“压栈”(Push),删除操作称为“弹栈”(Pop),而从栈顶读取元素或获取栈顶元素但不删除它称为“查看”(Peek)。
2.2 栈的基本操作推入元素:将一个元素添加到栈顶。
如果已经存在满员条件,则无法执行此操作。
弹出元素:从栈顶移除一个元素,并返回移除的值。
如果没有任何元素存在,则无法执行此操作。
查看栈顶元素:获取位于栈顶处的元素值,但不对其进行删除。
判断是否为空:检查栈是否为空。
数据结构 实验报告
![数据结构 实验报告](https://img.taocdn.com/s3/m/ec4edfe7fc0a79563c1ec5da50e2524de518d0b8.png)
数据结构实验报告一、实验目的数据结构是计算机科学中非常重要的一门课程,通过本次实验,旨在加深对常见数据结构(如链表、栈、队列、树、图等)的理解和应用,提高编程能力和解决实际问题的能力。
二、实验环境本次实验使用的编程语言为C++,开发工具为Visual Studio 2019。
操作系统为 Windows 10。
三、实验内容1、链表的实现与操作创建一个单向链表,并实现插入、删除和遍历节点的功能。
对链表进行排序,如冒泡排序或插入排序。
2、栈和队列的应用用栈实现表达式求值,能够处理加、减、乘、除和括号。
利用队列实现银行排队系统的模拟,包括顾客的到达、服务和离开。
3、二叉树的遍历与操作构建一棵二叉树,并实现前序、中序和后序遍历。
进行二叉树的插入、删除节点操作。
4、图的表示与遍历用邻接矩阵和邻接表两种方式表示图。
实现图的深度优先遍历和广度优先遍历。
四、实验步骤及结果1、链表的实现与操作首先,定义了链表节点的结构体:```cppstruct ListNode {int data;ListNode next;ListNode(int x) : data(x), next(NULL) {}};```插入节点的函数:```cppvoid insertNode(ListNode& head, int val) {ListNode newNode = new ListNode(val);head = newNode;} else {ListNode curr = head;while (curr>next!= NULL) {curr = curr>next;}curr>next = newNode;}}```删除节点的函数:```cppvoid deleteNode(ListNode& head, int val) {if (head == NULL) {return;}ListNode temp = head;head = head>next;delete temp;return;}ListNode curr = head;while (curr>next!= NULL && curr>next>data!= val) {curr = curr>next;}if (curr>next!= NULL) {ListNode temp = curr>next;curr>next = curr>next>next;delete temp;}}```遍历链表的函数:```cppvoid traverseList(ListNode head) {ListNode curr = head;while (curr!= NULL) {std::cout << curr>data <<"";curr = curr>next;}std::cout << std::endl;}```对链表进行冒泡排序的函数:```cppvoid bubbleSortList(ListNode& head) {if (head == NULL || head>next == NULL) {return;}bool swapped;ListNode ptr1;ListNode lptr = NULL;do {swapped = false;ptr1 = head;while (ptr1->next!= lptr) {if (ptr1->data > ptr1->next>data) {int temp = ptr1->data;ptr1->data = ptr1->next>data;ptr1->next>data = temp;swapped = true;}ptr1 = ptr1->next;}lptr = ptr1;} while (swapped);}```测试结果:创建了一个包含 5、3、8、1、4 的链表,经过排序后,输出为 1 3 4 5 8 。
利用栈来实现算术表达式求值的算法
![利用栈来实现算术表达式求值的算法](https://img.taocdn.com/s3/m/d3007463f6ec4afe04a1b0717fd5360cba1a8da5.png)
利用栈来实现算术表达式求值的算法利用栈来实现算术表达式求值的算法算术表达式是指按照一定规则组成的运算式,包含数字、运算符和括号。
在计算机中,求解算术表达式是一项基本的数学运算任务。
根据算术表达式的性质,我们可以考虑利用栈这一数据结构来实现求值算法。
一、算法思路首先,我们需要明确一个重要概念——逆波兰表达式(ReversePolish notation)。
逆波兰表达式是一种没有括号的算术表达式,其运算规则是先计算后面的数字和运算符,再计算前面的数字和运算符。
例如,对于算术表达式“3+4*5-6”,其对应的逆波兰表达式为“3 45 * +6 -”。
那么,我们可以利用栈来实现将中缀表达式转化为逆波兰表达式的过程,具体步骤如下:1. 创建两个栈——操作数栈和操作符栈。
2. 从左到右扫描中缀表达式的每一个数字和运算符,遇到数字则压入操作数栈中,遇到运算符则进行如下操作:(1)如果操作符栈为空或当前运算符的优先级大于栈顶运算符的优先级,则将当前运算符压入操作符栈中。
(2)如果当前运算符的优先级小于或等于栈顶运算符的优先级,则将栈顶运算符弹出并加入操作数栈中,重复此过程直到遇到优先级较低的运算符或操作符栈为空为止,然后将当前运算符压入操作符栈中。
3. 扫描完中缀表达式后,若操作符栈不为空,则将其中所有运算符弹出并加入操作数栈中。
4. 最终,操作数栈中存放的就是逆波兰表达式,我们可以按照逆波兰表达式的计算规则来计算其结果。
二、算法优点利用栈来实现算术表达式求值的算法具有以下优点:1. 代码简洁易懂,易于实现和维护。
2. 由于将中缀表达式转化为逆波兰表达式后,可以减少运算符的优先级关系而消除括号,从而减少求值的复杂度,提高程序的执行效率。
三、代码实现下面是利用栈来实现算术表达式求值的算法的Python代码实现:```pythonclass Stack:def __init__(self):self.items = []def push(self, item):self.items.append(item)def pop(self):return self.items.pop()def peek(self):return self.items[-1]def is_empty(self):return len(self.items) == 0def size(self):return len(self.items)def calculate(op_num1, op_num2, operator):if operator == "+":return op_num1 + op_num2elif operator == "-":return op_num1 - op_num2elif operator == "*":return op_num1 * op_num2elif operator == "/":return op_num1 / op_num2def infix_to_postfix(infix_expr):opstack = Stack()postfix_expr = []prec = {"+": 1, "-": 1, "*": 2, "/": 2, "(": 0} token_list = infix_expr.split()for token in token_list:if token.isdigit():postfix_expr.append(token)elif token == '(':opstack.push(token)elif token == ')':top_token = opstack.pop()while top_token != '(':postfix_expr.append(top_token)top_token = opstack.pop()else:while (not opstack.is_empty()) and(prec[opstack.peek()] >= prec[token]):postfix_expr.append(opstack.pop())opstack.push(token)while not opstack.is_empty():postfix_expr.append(opstack.pop())return " ".join(postfix_expr)def postfix_eval(postfix_expr):opstack = Stack()token_list = postfix_expr.split()for token in token_list:if token.isdigit():opstack.push(int(token))else:op_num2 = opstack.pop()op_num1 = opstack.pop()result = calculate(op_num1, op_num2, token) opstack.push(result)return opstack.pop()infix_expr = "3 + 4 * 5 - 6"postfix_expr = infix_to_postfix(infix_expr)print(postfix_expr)print(postfix_eval(postfix_expr))```四、总结算术表达式求值是一项常见的数学运算任务,利用栈这一数据结构来实现求值算法是一种简单有效的方法,它将中缀表达式转化为逆波兰表达式后,可以消除括号并减少运算符的优先级关系,从而提高程序的执行效率。
栈和队列的应用实例
![栈和队列的应用实例](https://img.taocdn.com/s3/m/3de9bdf2ba4cf7ec4afe04a1b0717fd5370cb240.png)
栈和队列的应用实例栈和队列都是常用的数据结构,在计算机科学中有着广泛的应用。
以下是一些常见的应用实例:1. 栈的应用实例●表达式求值:使用栈可以方便地对表达式进行求值,如逆波兰表达式求值。
●函数调用:函数调用时,每当进入一个函数,都会将上一个函数的现场信息压入栈中,然后在函数返回时再将其弹出,以便恢复上一个函数的执行现场。
●括号匹配:使用栈可以很方便地检查输入序列中括号的匹配情况。
2. 队列的应用实例●广度优先搜索:在图中进行广度优先搜索时常使用队列,因为它满足“先进先出”的特点,可以确保搜索的顺序是按层次来进行的。
●消息队列:在分布式系统中,消息队列经常用于实现进程之间的通信,以及任务的异步处理。
●缓冲区:在计算机中,经常需要通过使用缓冲区来平衡生产者和消费者之间的速度差异,队列就是一种常用的缓冲区实现方式。
以下是具体的应用实例:栈逆波兰表达式求值逆波兰表达式是一种不需要括号的算术表达式表示方法,它将运算符写在操作数的后面,因此也被称为“后缀表达式”。
例如,中缀表达式“3 + 4 * 2 / (1 - 5)”的逆波兰表达式为“3 4 2 * 1 5 - / +”。
逆波兰表达式求值时,可以使用栈来存储数字和运算符,具体过程如下:1. 遍历逆波兰表达式中的每个元素。
2. 如果当前元素是数字,则压入栈中。
3. 如果当前元素是运算符,则从栈中弹出两个操作数进行运算,并将结果压入栈中。
4. 遍历完逆波兰表达式后,栈顶即为表达式的值。
以下是Python语言实现逆波兰表达式求值的代码:def evalRPN(tokens: List[str]) -> int:stack = []for token in tokens:if token in '+-*/': # 运算符num2 = stack.pop()num1 = stack.pop()if token == '+':stack.append(num1 + num2)elif token == '-':stack.append(num1 - num2)elif token == '*':stack.append(num1 * num2)else:stack.append(int(num1 / num2))else: # 数字stack.append(int(token))return stack[0]该函数接受一个字符串列表tokens,其中包含了逆波兰表达式的所有元素。
基于栈结构的中缀表达式求值
![基于栈结构的中缀表达式求值](https://img.taocdn.com/s3/m/88b76f87da38376bae1fae26.png)
实验三基于栈结构的中缀表达式求值班级:计科131、问题描述从键盘输入一中缀表达式字符串,读字符串,利用栈结构实现表达式求值。
2、输入与输出输入:从键盘中缀表达式如: 32+5×(6-4)输出:计算结果423、需求分析1.定义两个栈结构,数栈用于存放表达式中的数,符号栈用于存放表达式中的符号,实现栈的运算2.在读数的时候考虑多位运算3.实现表达式求值4、开发工具与环境硬件设备:微型计算机系统软件环境:操作系统Windows,开发工具等等5、概要设计1.结构定义typedef struct /* 运算符栈 */{ char *base,*top;int stacksize;}SqStack;typedef struct /* 运算数栈 */{ int *base,*top;int stacksize;}SqStack1;int priority[7][7]={{'>', '>', '<', '<', '<', '>', '>'}, // +{'>', '>', '<', '<', '<', '>', '>'}, // -{'>', '>', '>', '>', '<', '>', '>'}, // *{'>', '>', '>', '>', '<', '>', '>'}, // /{'<', '<', '<', '<', '<', '=', }, // ({'>', '>', '>', '>', ' ', '>', '>'}, // ){'<', '<', '<', '<', '<', ' ', '='} // #};/*用于比较符号优先级的全局二维数组*/2.各函数模块void InitStack(SqStack *s);操作结果:初始化运算符栈。
栈的应用——表达式求值
![栈的应用——表达式求值](https://img.taocdn.com/s3/m/3b97f677178884868762caaedd3383c4bb4cb4cc.png)
栈的应⽤——表达式求值 表达式求值是程序设计语⾔编译中的⼀个基本问题,它的实现就是对“栈”的典型应⽤。
本⽂针对表达式求值使⽤的是最简单直观的算法“算符优先法”。
本⽂给出两种⽅式来实现表达式求值,⽅式⼀直接利⽤中缀表达式求值,需要⽤到两个栈,操作数栈和操作符栈。
⾸先置操作数栈为空栈,操作符栈仅有“#”⼀个元素。
依次读⼊表达式中的每个字符,若是操作数则进操作数栈,若是操作符则和操作符栈的栈顶运算符⽐较优先权作相应操作,直⾄整个表达式求值完毕。
⽅式⼆⾸先把中缀表达式转换为后缀表达式并存储起来,然后利⽤读出的后缀表达式完成求值,其本质上是⽅式⼀的分解过程。
表达式求值的代码如下:#include <iostream>#include "stack"#include "map"using namespace std;/* 只能求⼀位整数的加减乘除混合运算 */map<char, pair<int, int>> priority; // 存放各个操作符的栈内栈外优先级,first是栈内,second是栈外char infix[50]; // 存放初始的中缀表达式char postfix[50]; // 存放转化的后缀表达式int result;void MakePriority() // 构造运算符优先级表{priority.insert(make_pair('#', make_pair(0, 0))); // isp(#)=0, icp(#)=0priority.insert(make_pair('\n', make_pair(0, 0))); // isp(\n)=0, icp(\n)=0 表达式结尾的'#'⽤'\n'代替,这样可以省略表达式末尾的结束符'#'priority.insert(make_pair('(', make_pair(1, 6))); // isp(()=1, icp(()=6priority.insert(make_pair('*', make_pair(5, 4))); // isp(*)=5, icp(*)=4priority.insert(make_pair('/', make_pair(5, 4))); // isp(/)=5, icp(/)=4priority.insert(make_pair('%', make_pair(5, 4))); // isp(%)=5, icp(%)=4priority.insert(make_pair('+', make_pair(3, 2))); // isp(+)=3, icp(+)=2priority.insert(make_pair('-', make_pair(3, 2))); // isp(-)=3, icp(-)=2priority.insert(make_pair(')', make_pair(6, 1))); // isp())=6, icp())=1}void InfixToPostfix() // 把中缀表达式转换为后缀表达式{int i = 0;stack<char> optrStack; // 操作符栈char optr; // optr为栈顶的操作符optrStack.push('#');while (!optrStack.empty()){if (isdigit(infix[i])) // 是操作数则直接输出(追加到postfix结尾){postfix[strlen(postfix)] = infix[i];postfix[strlen(postfix) + 1] = '\0';i++; // 读⼊中缀表达式的下⼀个字符}else// 是操作符, ⽐较优先级{optr = optrStack.top(); // 取出栈顶操作符if (priority[infix[i]].second > priority[optr].first) // icp(infix[i]) > isp(optr),infix[i]⼊栈{optrStack.push(infix[i]);i++;}else if (priority[infix[i]].second < priority[optr].first)// icp(infix[i]) < isp(optr),optr退栈并输出{postfix[strlen(postfix)] = optr;postfix[strlen(postfix) + 1] = '\0';optrStack.pop();}else// icp(infix[i]) = isp(optr),退栈但不输出,若退出的是'(',则继续读⼊下⼀个字符{optrStack.pop();if (optr == '(')i++;}}}}void CalculateByPostfix() // 通过后缀表达式求值{int i = 0;stack<int> opndStack; // 操作数栈int left, right; // 左右操作数int value; // 中间结果int newOpnd;while (postfix[i] != '#' && i < strlen(postfix)){switch (postfix[i]){case'+':right = opndStack.top(); // 从操作数栈中取出两个操作数opndStack.pop();left = opndStack.top();opndStack.pop();value = left + right;opndStack.push(value); // 中间结果⼊栈break;case'-':right = opndStack.top();opndStack.pop();left = opndStack.top();opndStack.pop();value = left - right;opndStack.push(value);break;case'*':right = opndStack.top();opndStack.pop();left = opndStack.top();opndStack.pop();value = left * right;opndStack.push(value);break;case'/':right = opndStack.top();opndStack.pop();left = opndStack.top();opndStack.pop();if (right == 0){cerr << "Divide by 0!" << endl;}else{value = left / right;opndStack.push(value);}break;default:newOpnd = (int)(postfix[i] - 48); // 操作数直接⼊栈opndStack.push(newOpnd);break;}i++;}result = opndStack.top();}void CalculateByInfix() // 直接利⽤中缀表达式求值{int i = 0;stack<char> optrStack; // 操作符栈stack<int> opndStack; // 操作数栈char optr; // optr为操作符栈顶的操作符int left, right, value; // 左右操作数以及中间结果optrStack.push('#');optr = optrStack.top();while (!optrStack.empty()) // 直到操作符栈为空{if (isdigit(infix[i])) // 是操作数, 进操作数栈{value = (int)(infix[i] - 48);opndStack.push(value);i++;}else// 是操作符, ⽐较优先级{optr = optrStack.top(); // 取出操作符栈顶的操作符if (priority[infix[i]].second > priority[optr].first) // icp(infix[i]) > isp(optr),infix[i]⼊栈 {optrStack.push(infix[i]);i++;}else if (priority[infix[i]].second < priority[optr].first) // icp(infix[i]) < isp(optr),optr退栈并输出{optrStack.pop();right = opndStack.top(); // 从操作数栈中取出两个操作数opndStack.pop();left = opndStack.top();opndStack.pop();switch (optr){case'+':value = left + right;opndStack.push(value); // 中间结果⼊栈break;case'-':value = left - right;opndStack.push(value); // 中间结果⼊栈break;case'*':value = left * right;opndStack.push(value); // 中间结果⼊栈break;case'/':if (right == 0){cerr << "Divide by 0!" << endl;}else{value = left / right;opndStack.push(value);}break;default:break;}}else{optrStack.pop();if (optr == '(')i++;}}}result = opndStack.top();}int main(){MakePriority(); // 构造运算符优先级表cout << "请输⼊中缀表达式:";cin >> infix;cout << "直接利⽤中缀表达式求值为:";CalculateByInfix();cout << result << endl;cout << "转化为后缀表达式:";InfixToPostfix();for (int i = 0;i < strlen(postfix);i++){cout << postfix[i];}cout << endl;cout << "利⽤后缀表达式求值为:";CalculateByPostfix();cout << result << endl;return0;} 为了⽅便起见,本⽂只是简单的设计了⼀个针对⼀位整数的四则运算进⾏求值的算法,对于处理多位整数的四则运算,需要对本⽂接受输⼊的数据类型进⾏“升阶”,把字符数组换成字符串数组,将⼀个整数的多位数字存⼊⼀个字符串进⾏处理。
用栈解决表达式求值问题的c语言代码
![用栈解决表达式求值问题的c语言代码](https://img.taocdn.com/s3/m/08e661600622192e453610661ed9ad51f11d5469.png)
栈是一种常见的数据结构,用于解决许多算法和数据处理问题。
在编程中,栈通常用于处理表达式求值问题。
本篇文章将介绍如何使用栈解决表达式求值问题,并给出对应的C语言代码。
1. 表达式求值问题介绍表达式求值是指计算一个数学表达式的值,通常涉及到四则运算、括号和优先级等概念。
给定一个表达式“3 + 4 * 2”,我们需要得到其计算结果为11。
在编程中,需要将该表达式转换为计算机可识别的形式,并使用算法进行求值。
2. 中缀表达式、前缀表达式和后缀表达式在计算机中常见的表达式有三种形式:中缀表达式、前缀表达式和后缀表达式。
其中,中缀表达式是通常人们在日常生活中使用的表达式形式,如“3 + 4 * 2”。
前缀表达式是运算符位于操作数之前的形式,例如“+ 3 * 4 2”。
后缀表达式则是运算符位于操作数之后的形式,例如“3 4 2 * +”。
3. 使用栈解决表达式求值问题在解决表达式求值问题时,我们可以利用栈的特性来简化计算过程。
具体步骤如下:3.1 将中缀表达式转换为后缀表达式我们需要将中缀表达式转换为后缀表达式,这样可以简化表达式的计算顺序。
具体转换规则如下:- 从左至右扫描中缀表达式的每个数字或符号。
- 如果是操作数,则直接输出。
- 如果是运算符,则弹出栈中所有优先级大于或等于该运算符的运算符,并将其压入栈中,然后压入该运算符。
- 如果是括号,则根据括号的不同情况进行处理。
通过以上规则,我们可以将中缀表达式转换为后缀表达式。
3.2 计算后缀表达式的值得到后缀表达式后,我们可以利用栈来计算其值。
具体步骤如下:- 从左至右扫描后缀表达式的每个数字或符号。
- 如果是操作数,则压入栈中。
- 如果是运算符,则弹出栈中的两个操作数进行相应的运算,并将结果压入栈中。
- 继续扫描直到表达式结束,栈中的值即为所求结果。
通过以上步骤,我们可以使用栈来解决表达式求值问题。
4. C语言代码实现以下是使用C语言实现栈来解决表达式求值问题的代码示例:```c#include <stdio.h>#include <stdlib.h>#include <string.h>typedef struct {int top;int capacity;int* array;} Stack;Stack* createStack(int capacity) {Stack* stack = (Stack*)malloc(sizeof(Stack));stack->capacity = capacity;stack->top = -1;stack->array = (int*)malloc(stack->capacity * sizeof(int)); return stack;}int isFull(Stack* stack) {return stack->top == stack->capacity - 1; }int isEmpty(Stack* stack) {return stack->top == -1;}void push(Stack* stack, int item) {if (isFull(stack)) return;stack->array[++stack->top] = item;}int pop(Stack* stack) {if (isEmpty(stack)) return -1;return stack->array[stack->top--];}int evaluatePostfix(char* exp) {Stack* stack = createStack(strlen(exp)); for (int i = 0; exp[i]; i++) {if (isdigit(exp[i])) {push(stack, exp[i] - '0');} else {int val1 = pop(stack);int val2 = pop(stack);switch (exp[i]) {case '+':push(stack, val2 + val1); break;case '-':push(stack, val2 - val1); break;case '*':push(stack, val2 * val1); break;case '/':push(stack, val2 / val1); break;}}}return pop(stack);}int m本人n() {char exp[] = "34*2+";printf("The value of s is d\n", exp, evaluatePostfix(exp));return 0;}```以上代码实现了栈的基本功能,并利用栈来计算后缀表达式的值。
栈的应用表达式求值的原理
![栈的应用表达式求值的原理](https://img.taocdn.com/s3/m/b4eaf98688eb172ded630b1c59eef8c75ebf9550.png)
栈的应用:表达式求值的原理一、栈的基本原理1.栈是一种具有特殊操作的线性数据结构。
2.栈的特点是后进先出(LIFO,Last In First Out)的存取方式。
3.栈有两个基本操作:入栈和出栈。
二、表达式求值的概念1.表达式是由运算符和运算对象组成的序列。
2.表达式求值是指根据运算符的优先级和结合性来计算表达式的值。
三、中缀表达式与后缀表达式1.中缀表达式:运算符位于运算对象的中间。
–例如:2 + 32.后缀表达式(逆波兰表达式):运算符位于运算对象的后面。
–例如:2 3 +四、中缀转后缀表达式1.利用栈实现中缀表达式到后缀表达式的转换。
2.遍历中缀表达式中的每个字符,若为数字,则输出到后缀表达式中;若为运算符,则根据优先级进行处理。
3.将运算符入栈,直到出现低优先级的运算符或左括号。
4.遇到右括号时,将栈中的运算符出栈并输出,直到遇到左括号。
5.将剩余的运算符出栈并输出。
五、后缀表达式求值1.利用栈实现后缀表达式的求值。
2.遍历后缀表达式中的每个字符,若为数字,则入栈;若为运算符,则弹出栈中的两个数字进行计算,并将结果入栈。
3.最后栈中的唯一元素即为表达式的求值结果。
六、示例假设要求解的中缀表达式为:2 + 3 * 4 - 5 1. 将中缀表达式转换为后缀表达式:2 3 4 * + 5 - 2. 根据后缀表达式求值的原则,遍历后缀表达式进行计算: - 遇到数字2,入栈; - 遇到数字3,入栈; - 遇到运算符*,弹出栈中的两个数字3和2进行计算得到6,并将结果入栈; - 遇到运算符+,弹出栈中的两个数字6和4进行计算得到10,并将结果入栈; - 遇到数字5,入栈; - 遇到运算符-,弹出栈中的两个数字10和5进行计算得到5,并将结果入栈。
3. 栈中的唯一元素5即为表达式的求值结果。
七、总结1.栈的应用在表达式求值中起到关键作用。
2.利用栈可以将中缀表达式转换为后缀表达式,并通过对后缀表达式的求值获得最终结果。
数据结构强化习题课汇总
![数据结构强化习题课汇总](https://img.taocdn.com/s3/m/d1bcb1120722192e4536f6e4.png)
第一章绪论考点1 数据结构基础知识1.数据的逻辑结构是指(),数据的存储结构是指()分析:数据结构包括三方面的内容:数据的逻辑结构、存储结构和数据的运算。
其中,逻辑结构是指各数据元素之间的逻辑关系,存储结构是指逻辑结构用计算机语言的实现。
解答:数据元素之间的逻辑关系;数据的逻辑结构用计算机语言的实现。
2.在数据结构中,从逻辑上可以把数据结构分为:(A)A 线性和非线性结构B 紧凑和非紧凑结构C 动态和静态结构D 内部和外部结构分析:数据结构中,逻辑上可以把数据结构分成线性结构和非线性结构。
线性结构的顺序存储结构是一种随机存取的存储结构,线性表的链式存储结构是一种顺序存储结构。
线性表若采用链式存储表示时,所有结点之间的存储单元地址可连续可不连续。
逻辑结构与数据元素本身的形式、内容、相对位置、所含结点个数无关。
关键考点点评:线性结构的特征,有且仅有一个开始结点和终端结点,所有结点最多只有一个直接前驱和后继。
栈和队列。
非线性结构的结点有多个前驱或后继,树和图。
3.数据结构在物理上可以分为()存储结构和链式存储结构。
分析:物理存储解答:顺序4.下列术语中,()与数据的存储结构无关A 循环队列B 堆栈C 散列表D 单链表解答: A5.()不是算法所必须具备的特性A 有穷性B 确定性C 高效性D 可行性分析:算法的五个重要特征:有穷性、确定性、可行性、输入和输出。
解答:C考点2 时间复杂度计算1.设n是描述问题规模的非负整数,下面程序段的时间复杂度是()2.第二章线性表考点1 线性表的基本概念1.线性表是n个()的有限序列。
A 字符B数据元素 C 由数据项 D 信息项解析:解答 B2.线性表是一个()。
A 有限序列,可以为空B 有限序列,不能为空C 无限序列,可以为空D 无限序列,不能为空解答 A关键考点点评:对于非空线性表1.有且仅有一个开始结点,没有直接前驱,有且仅有一个直接后继;2.有且仅有一个终结结点,没有直接后继,有且仅有一个直接前驱;3.其余的内部结点都有且仅有一个直接前驱和后继3.单链表不能随机存取元素原因是:要得到元素的存储地址,必须()解答:从起始结点开始扫描以得到其地址注:顺序表可以,但是链表不行考点2 线性表的顺序存储结构1.下述()是顺序存储结构的优点A 插入运算方便B 可方便地用于各种逻辑结构的存储表示C 存储密度大D 删除运算方便解答: C2.线性表的()存储结构是随机存储结构。
利用栈进行表达式求值
![利用栈进行表达式求值](https://img.taocdn.com/s3/m/aa15a848cf84b9d528ea7a15.png)
myStack.top = myStack.base + myStack.stacksize;
myStack.stacksize += STACKINCREMENT;
#include "Stdafx.h"
#include <stdio.h>
#include <malloc.h>
#define STACK_INIT_SIZE 100
#define STACKINCREMENT 10
typedef struct {
int *base;
int *top;
int stacksize;
if(isNum(c)) {
push(opnd, ((int)c-48));
c = getchar();
} else {
switch(precede((char)getTop(oprt), c)) {
case '<' : push(oprt, c); c = getchar(); break;
case '=' : pop(oprt, t); c = getchar(); break;
default : return '>';
} break;
case '(' :
switch (c2) {
case ')' : return '='; break;
栈的应用实验报告
![栈的应用实验报告](https://img.taocdn.com/s3/m/bc6ef545e97101f69e3143323968011ca300f73c.png)
栈的应用实验报告栈的应用实验报告引言:栈是一种常见的数据结构,它具有后进先出(Last In First Out,LIFO)的特点。
在计算机科学中,栈被广泛应用于各种领域,如编译器、操作系统、图形处理等。
本实验旨在通过实际应用场景,探索栈的应用。
一、栈的基本概念和操作栈是一种线性数据结构,它由一系列元素组成,每个元素都有一个前驱元素和一个后继元素。
栈的基本操作包括入栈(Push)和出栈(Pop)。
入栈将元素添加到栈的顶部,而出栈则将栈顶元素移除。
此外,栈还具有查看栈顶元素(Top)和判断栈是否为空(IsEmpty)的操作。
二、栈在表达式求值中的应用栈在表达式求值中发挥着重要作用。
例如,当我们需要计算一个数学表达式时,可以通过将表达式转换为后缀表达式,并利用栈来进行求值。
栈中存储操作数,当遇到运算符时,从栈中弹出相应数量的操作数进行计算,再将结果入栈。
通过这种方式,我们可以实现高效的表达式求值。
三、栈在函数调用中的应用栈在函数调用中也扮演着重要角色。
当我们调用一个函数时,计算机会将函数的返回地址、参数和局部变量等信息存储在栈中。
这样,当函数执行完毕后,可以从栈中恢复之前的上下文,继续执行调用函数的代码。
栈的这种特性使得递归函数的实现成为可能,同时也为程序的模块化提供了便利。
四、栈在迷宫求解中的应用栈在迷宫求解中也能发挥重要作用。
当我们需要找到从起点到终点的路径时,可以利用栈来存储当前路径上的位置。
从起点开始,我们按照某种策略选择下一个位置,并将其入栈。
如果当前位置无法继续前进,则将其出栈,并选择下一个位置。
通过不断重复这个过程,直到找到终点或者栈为空,我们就能得到迷宫的解。
五、栈在撤销和恢复操作中的应用栈在撤销和恢复操作中也能发挥重要作用。
当我们在编辑文档或者绘图时,经常需要进行撤销和恢复操作。
栈可以用来记录每次操作的状态,当用户选择撤销时,从栈中弹出最近的操作,并将文档或图形恢复到之前的状态。
通过这种方式,我们可以提供良好的用户体验,同时也方便用户进行操作的回溯。
考研计算机学科专业基础综合-6-1
![考研计算机学科专业基础综合-6-1](https://img.taocdn.com/s3/m/e49ac245ed630b1c59eeb5df.png)
考研计算机学科专业基础综合-6-1(总分:149.96,做题时间:90分钟)一、{{B}}单项选择题{{/B}}(总题数:40,分数:80.00)1.下列叙述中,正确的是______。
Ⅰ.非空循环单链表head的尾结点p满足p→next=headⅡ.带头结点的循环单链表的头指针为head,如果head→next→next→next=head成立,则该单链表的长度为3Ⅲ.静态链表中的指针表示的是下一个元素在数组中的位置Ⅳ.将长度为n的单链表链接在长度为m的单链表之后的算法时间复杂度为O(1)∙ A.仅Ⅰ、Ⅱ、Ⅲ∙ B.Ⅰ、Ⅱ、Ⅲ、Ⅳ∙ C.仅Ⅰ、Ⅲ∙ D.仅Ⅰ、Ⅲ、Ⅳ(分数:2.00)A.B.C. √D.解析:[解析] Ⅰ:非空循环单链表的尾结点指针应该指向链表头,即p→next==head,故Ⅰ正确。
Ⅱ:head指向头结点,head→next就指向第一个结点。
既然head→next→next→next=head,说明此循环链表共有3个结点(包含头结点),而单链表中增加头结点仅仅是为了更方便地进行插入和删除操作,它并不存储线性表的元素,故不能算为单链表结点,故此单链表的长度为2,故Ⅱ错误。
Ⅲ:静态链表中的指针所存储的不再是链表中的指针域,而是其下一个结点在数组中的位詈,即数组下标,故Ⅲ正确。
Ⅳ:将链表连接起来只需O(1)的操作,但找到具有m个结点链表的尾结点需遍历该链表,所以时间复杂度应该为O(m),故Ⅳ错误。
2.利用栈求表达式的值时,设立运算数栈s。
假设栈S只有两个存储单元,在下列表达式中,不发生溢出的是______。
∙ A.A-B*(C-D)∙ B.(A-B)*C-D∙ C.(A-B*C)-D∙ D.(A-B)*(C-D)(分数:2.00)A.B. √C.D.解析:[解析] 利用栈求表达式的值时,需要设立运算符栈和运算数栈,下面仅举一例。
例如,求2×(5-3)+6/2的过程如下表所示。
栈的相关操作及应用
![栈的相关操作及应用](https://img.taocdn.com/s3/m/ce72c9540a4e767f5acfa1c7aa00b52acfc79cd3.png)
栈的相关操作及应用栈是一种具有特殊结构的线性数据结构,它的特点是只能在一端进行操作。
这一端被称为栈顶,另一端被称为栈底。
栈的基本操作包括入栈操作(Push)和出栈操作(Pop)。
入栈操作指的是将数据元素插入到栈顶的位置,同时栈顶指针向上移动一位。
出栈操作指的是将栈顶元素删除,并将栈顶指针向下移动一位。
栈还具有一个基本操作——取栈顶元素(Peek),它可以返回栈顶元素的值而不删除它。
栈的应用非常广泛,下面我将介绍一些常见的应用场景。
1. 括号匹配问题:在编程中,经常需要判断一段代码中的括号是否匹配。
这时可以使用栈来解决。
遍历整个代码,遇到左括号就入栈,遇到右括号时判断栈顶元素是否为对应的左括号,如果是,则出栈,继续遍历;如果不是,则括号不匹配。
最后判断栈是否为空,如果为空,则所有括号都匹配。
2. 函数调用栈:在程序执行过程中,每次调用函数时都会将当前函数的局部变量、函数参数等保存在栈中。
当函数返回时,栈顶元素出栈,程序回到之前的函数继续执行。
这样可以实现程序对函数执行过程的跟踪和管理。
3. 表达式求值:在计算机科学中,中缀表达式(如:3 + 4 * 5)通常不方便计算机直接求值,而将中缀表达式转换为后缀表达式(也称为逆波兰表达式)则可以方便计算机求值。
这个转换的过程可以使用栈来实现。
遍历中缀表达式,遇到操作数直接输出,遇到运算符则与栈顶运算符进行比较,如果优先级高于栈顶运算符,则入栈,如果低于或等于栈顶运算符,则将栈顶运算符出栈直到遇到优先级低于它的运算符,然后将当前运算符入栈。
最后将栈中剩余的运算符依次出栈输出。
4. 浏览器的前进和后退:浏览器的前进和后退功能可以使用两个栈来实现。
一个栈用于保存浏览的历史记录,每当用户点击链接或提交表单时,将当前页面的URL入栈。
另一个栈用于保存前进的页面,当用户点击后退按钮时,将历史记录栈顶元素出栈并入栈到前进栈中,然后将前进栈顶元素出栈并跳转到该页面。
5. 编译器的语法分析:编译器在进行语法分析时通常会使用到栈。
王道模拟试题(前3套)
![王道模拟试题(前3套)](https://img.taocdn.com/s3/m/0aab5aeb5ef7ba0d4a733b39.png)
25. 设有 3 个作业,它们的到达时间和运行时间如下表所示,并在一台处理机上按单道方式运行。如按高 响应比优先算法,则作业执行的次序和平均周转时间依次为( 作业提交时间和运行时间表 作业号 1 2 3 A. J1,J2,J3、1.73 C. J1,J3,J2、2.08
int counter=6; P1: computing; counter=counter+1; P2: printing; counter=counter-2;
int A[50][50]; for(int i=0;i<50;i++) for(int j=0;j<50;j++) A[i][j]=0;
若在程序执行时内存只有一个存储块用来存放数组信息,则该程序执行时产生( A. 1 B. 50 C. 100 D. 2500 ) 。
)次缺页中断。
29. 若存储单元长度为 n,存放在该存储单元的程序长度为 m,则剩下长度为 n-m 的空间称为该单元的内 部碎片。下面存储分配方法中,哪种存在内部碎片( I. 固定式分区 II. 动态分区 IV. 段式管理 A. I 和 II B. I、III 和 V III. 页式管理 VI.请求段式管理 D. III 和 V ) 。 C. IV、V 和 VI V. 段页式管理
int n=0xA1B6; unsigned int m=n; m=m>>1; //m 右移一位
)时,x<-1/2 成立。
14. 设机器数字长 16 位,有一个 C 语言程序段如下:
则在执行完该段程序后,m 的值为( A. 50DBH B. FFB6H
) D. D0DBH ) 。 (假设不考虑一致维护位) D. 64× 13 bit ) 。
考研计算机学科专业基础综合-48_真题-无答案
![考研计算机学科专业基础综合-48_真题-无答案](https://img.taocdn.com/s3/m/825630126d175f0e7cd184254b35eefdc8d3158f.png)
考研计算机学科专业基础综合-48(总分151,考试时间90分钟)一、单项选择题1. 已知一个栈的进栈序列是1、2、3、…、n,其输出序列为p1、p2、p3、…、pn,若p1=3,则p2为______。
A. 2或4、5、…、n都有可能B. 可能是1C. 一定是2D. 只可能是2或42. 利用栈求表达式的值时,设立运算数栈OPEN。
假设OPEN只有两个存储单元,则在下列表达式中,不会发生溢出的是______。
A. A-B*(C-D)B. (A-B)*C-DC. (A-B*C)-DD. (A-B)*(C-D)3. 已知A[1...N]是一棵顺序存储的完全二叉树,9号结点和11号结点共同的祖先是______。
A. 4B. 6C. 2D. 84. 在常用的描述二叉排序树的存储结构中,关键字值最大的结点是______。
A. 左指针一定为空B. 右指针一定为空C. 左、右指针均为空D. 左、右指针均不为空5. 分别以下列序列构造二叉排序树,与用其他三个序列所构造的结果不同的是______。
A. (100,80,90,60,120,110,130)B. (100,120,110,130,80,60,90)C. (100,60,80,90,120,110,130)D. (100,80,60,90,120,130,110)6. 设无向图G=(V,E)和G"=(V",E"),如果G"是G的生成树,则下面说法错误的是______。
A. G"是G的子图B. G"是G的连通分量C. G"是G的极小连通子图且V=V",D. G"是G的一个无环子图7. 若G是一个具有36条边的非连通无向简单图,则图G的结点数至少是______。
A. 11B. 10C. 9D. 88. 在有向图G的拓扑序列中,若顶点Vi在顶点Vj之前,则下列情形不可能出现的是______。
计算机学科专业基础综合模拟1
![计算机学科专业基础综合模拟1](https://img.taocdn.com/s3/m/a4a33a916f1aff00bed51efe.png)
[模拟] 计算机学科专业基础综合模拟1单项选择题第1题:利用栈求表达式的值时,设立运算数栈OPND。
假设OPND只有两个存储单元,在下列表达式中,不发生溢出的是( )。
A.A—B*(C—D)B.(A—B)*C—DC.(A—B*C)—DD.(A—B)*(C—D)参考答案:B第2题:已知输入序列为abcd,经过输出受限的双端队列后,能得到的输出序列是( )。
A.dacbB.cadbC.dbcaD.以上答案都不对参考答案:B输出受限的双端队列是指删除限制在一端进行,而插入允许在两端进行的队列。
分析选项A,输入序列为abcd,输出序列为dacb,由输出受限性质可知以da开头的结果只有dabc,选项A为错误答案。
分析选项B,输入序列为abcd,输出序列为cadb,其输入输出顺序为:先在输出端输入a,然后在非输出端输入b,这时队列中的序列为ba,再在输出端输入c,这时队列中的序列为bac:;输出c,再输出a;再在输出端输入d,这时队列中的序列为bd;输出d,再输出b。
最后得到输出序列为cadb。
分析选项C,输入序列为abcd,输出序列为dbca,由输出受限性质可知以db开头的结果只有dbad,选项C为错误答案。
第3题:一个具有1025个结点的二叉树的高度为( )。
A.11B.10C.11至1025之间D.10至1024之间参考答案:C一棵二叉树每层只有1个结点,则具有1025个结点的二叉树的最大高度为1025。
一个具有1025个结点的完全二叉树的高度为11。
这一个具有1025个结点的二叉树的高h为11至1025之间。
第4题:以下关于二叉排序树的说法正确的是( )。
Ⅰ在二叉排序树中,每个结点的关键字都比左孩子关键字大,比右孩子关键字小Ⅱ每个结点的关键字都比左孩子关键字大,比右孩子关键字小,这样的二叉树都是二又排序树Ⅲ在二叉排序树中,新插入的关键字总是处于最底层Ⅳ在二叉排序树中,新结点总是作为叶子结点来插入的Ⅴ二叉排序树的查找效率和二叉排序树的高度有关A.Ⅰ、Ⅱ、Ⅳ、ⅤB.Ⅱ、Ⅲ、ⅣC.Ⅰ、Ⅲ、ⅤD.Ⅰ、Ⅳ、Ⅴ参考答案:D对于二叉排序树,左子树上所有记录的关键字均小于根记录的关键字;右子树上所有记录的关键字均大于根记录的关键字。
栈实现表达式的简单求值
![栈实现表达式的简单求值](https://img.taocdn.com/s3/m/e87d7bfe866fb84ae45c8df7.png)
利用栈编写表达式求值程序:输入含有“+”、“-”、“*”、“/”四则运算的表达式,其中负数要用(0-正数)表示,并以=结束。
要求输出表达式的值此题目可选做。
注意:计算的结果数值不可以大于79.#include<stdio.h>#include<malloc.h>#define OK 1#define ERROR 0#define STACK_INIT_SIZE 100 // 存储空间初始分配量typedef struct{char *base;char *top;int stacksize;}Stack;int InitStack(Stack &S){S.base=(char *)malloc(STACK_INIT_SIZE*sizeof(char)); if(!S.base) return ERROR;S.top=S.base;S.stacksize=STACK_INIT_SIZE;return OK;}int Pop(Stack &S,char &e){if(S.top==S.base) return ERROR;e=*--S.top;return OK;}int GetTop(Stack S,char &e){if(S.top==S.base) return ERROR;e=*--S.top;return OK;}int Push(Stack &S,char ch){if(S.top-S.base>=S.stacksize){S.base=(char*)realloc(S.base,(S.stacksize+10)*sizeof(char)); if(!S.base) return ERROR;S.top=S.base+S.stacksize;S.stacksize+=10;}*S.top++=ch;return OK;}char Compare(char &e,char ch){switch(e){case '+':if(ch=='+'||ch=='-'||ch==')') return '>';else return '<';break;case '-':if(ch=='+'||ch=='-'||ch==')') return '>';else return '<';break;case '*':if(ch=='(')return '<';else return '>';break;case '/':if(ch=='(')return '<';else return '>';break;case '(':if(ch==')')return '=';else return '<';break;case ')':return '>';break;}}int Cal(char a,char theta,char b) {int s;a-=48;b-=48;switch(theta){case '+':s=a+b;break;case '-':s=a-b;break;case '*':s=a*b;break;case '/':s=a/b;break;}return s;}int StackEmpty(Stack S){if(S.top==S.base) return OK; return ERROR;}int Operator(){Stack CS;Stack NS;char ch,e;char a,b,theta;InitStack(CS);InitStack(NS);//Push(CS,'=');ch=getchar();while(ch!='='){if(ch>='0'&&ch<='9'){Push(NS,ch);ch=getchar();if(ch>='0'&&ch<='9'){Pop(NS,a);Push(NS,((a-48)*10+(ch-48))+48); ch=getchar();}}else{if(StackEmpty(CS)){Push(CS,ch);ch=getchar(); continue;}GetTop(CS,e);switch(Compare(e,ch)) {case '<':Push(CS,ch); ch=getchar();break;case '=':Pop(CS,e);ch=getchar();break;case '>':Pop(CS,theta);Pop(NS,a);Pop(NS,b);Push(NS,Cal(b,theta,a)+48); break;}}}while(Pop(CS,theta)){Pop(NS,a);Pop(NS,b);Push(NS,(Cal(b,theta,a)+48)); }GetTop(NS,ch);return (ch-48);}int main(){printf("%d\n",Operator()); return 0;}输入格式第一行:一个算术表达式输出格式第一行:算术表达式的值输入样例3*(9-7)=(0-12)*((5-3)*3)/(2+2)=输出样例6-18。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
数据结构课程设计姓名:杨颂敬班级:软件0901班学号:0930*******目录:1.需求分析 (1)2.概要设计 (1)3.详细设计................................. 3-6 4.调试分析................................. 6-8 5.用户使用说明 (8)6.测试结果 (9)7.附录 (9)利用栈求表达式的值,可供小学生作业,并能给出分数。
1.需求分析任务:通过此系统可以实现如下功能:此系统能够输入一个表达式,并计算该表达式的值。
可以根据计算结果给出分数。
能供小学生进行简单的四则运算,此外这里特别强调括号的匹配!要求:根据以上功能说明,设计运算信息,堆栈的存储结构,设计程序完成功能;2. 概要设计在此说明每个部分的算法设计说明(可以是描述算法的流程图),每个程序中使用的存储结构设计说明(如果指定存储结构请写出该存储结构的定义)。
主菜单3.详细设计#include "string.h"#include "stdio.h"#include"conio.h"#define maxsize 100#include "ctype.h"typedef char datatype;typedef struct{datatype stack[maxsize];int top;} seqstack;void stackinitiate(seqstack *s){s->top=0;}int stacknotempty(seqstack s){if(s.top<=0) return 0;else return 1;}int stackpush(seqstack *s, datatype x) {if(s->top>=maxsize){printf("堆栈已满无法插入!\n");return 0;}else{s->stack[s->top]=x;s->top++;return 1;}}int stackpop(seqstack *s,datatype *d) {if(s->top<=0){printf("堆栈已空无数据元素出栈!\n");return 0;}else{s->top--;*d=s->stack[s->top];return 1;}}int stacktop(seqstack s,datatype *d){if(s.top<=0){printf("堆栈已空!\n");return 0;}else{*d=s.stack[s.top-1];return 1;}}void expiscorrect(char exp[], int n){seqstack mystack;int i;char c;stackinitiate(&mystack);for(i=0;i<n;i++){if(exp[i]=='(')stackpush(&mystack, exp[i]);else if((exp[i]==')') && stacknotempty(mystack) && stacktop(mystack,&c) && c=='(') stackpop(&mystack,&c);else if((exp[i]==')') && !stacknotempty(mystack)){printf("右括号多余左括号!\n");return ;}}if(stacknotempty(mystack))printf("左括号多余右括号!\n");elseprintf("左右括号匹配正确!\n");}static float ans[50];static int count=0;static int right=0;static float yourresult[50];int postexp(char exp[]){seqstack mystack;datatype x1,x2;int i;int j=0,ls;int top=0;int isFalse=0;int isRead=0;char oprator = ' ';stackinitiate(&mystack);for(i=0;exp[i]!='#';i++){if(isdigit(exp[i])){top=(int)(exp[i]-48);top*=10;}else{if (isRead == 0){isRead++;top/=10;stackpush(&mystack,top);oprator = exp[i];top=0;}else if (isRead == 1){stackpush(&mystack,top);if (isRead == 1){isRead++;stackpop(&mystack,&x2);}stackpop(&mystack,&x1);ls=x1;x1=x2;x2=ls;x1/=10;switch(oprator){case '+': {x1+=x2;break;}case '-': {x1-=x2;break;}case '*': {x1*=x2;break;}case '/':{if(x2==0.0){printf("除数为0错!\n");isFalse=1;}else{x1/=x2;}};break;}oprator = exp[i];x2=x1;top=0;}}}if (isRead == 0){isRead++;top/=10;stackpush(&mystack,top);oprator = exp[i];top=0;}else if (isRead == 1){stackpush(&mystack,top);if (isRead == 1){isRead++;stackpop(&mystack,&x2);}stackpop(&mystack,&x1);ls=x1;x1=x2;x2=ls;x1/=10;switch(oprator){case '+': {x1+=x2;break;}case '-': {x1-=x2;break;}case '*': {x1*=x2;break;}case '/':{if(x2==0.0){printf("除数为0错!\n");isFalse=1;}else{x1/=x2;}};break;}oprator = exp[i];x2=x1;top=0;}if (isFalse == 1) return -1;ans[count] = x1;printf("请输入您计算的结果:");scanf("%f",&yourresult[count]);if(ans[count]==yourresult[count]) right++;count++;getchar();}int main(){int i=0;char exp[100];printf(" ------计算表达式------\n使用说明:\n");printf(" 1.请输入要计算的表达式,以#结尾,例如1+2#\n");printf(" 2.结束计算请输入符号$\n");printf(" 3.在表达式中可以运算括号,中括号[]和大括号{}统一使用小括号代替()!\n");printf(" 4.程序输入格式错误时,将会自动结束程序,请注意格式正确!\n");printf("请输入要计算的表达式,以#结尾。
结束程序输入$。
\n");// c=getchar();scanf("%s",exp);while(exp[i]!='$'){expiscorrect(&exp,i);postexp(&exp);printf("-------------------------------------------\n");printf("请输入下一个表达式,以#结尾。
结束程序输入$。
\n");scanf("%s",exp);// c=getchar();}printf("\n\n ******您的成绩单*******\n");printf("----------------------------------------\n");printf(" 序号正确答案您的答案结论\n");for(i=0;i<count;i++){printf("表达式%d %.2f %.2f %s\n",i+1,ans[i],yourresult[i],ans[i]==yourresult[i]?"正确!":"错误!");}printf("----------------------------------------\n");printf("解答题目总共为%d道,其中\n",count);printf("正确解答%d道题,错误解答%d道题。
\n *****最后得分为%d分!*****\n", right,count-right,right*100/count);printf("----------------------------------------\n");getchar();getchar();return 0;}4.调试分析5.用户使用说明运行程序,然后根据提示进行计算并给出分数,然后退出。