数据结构实验4四则运算表达式求值实验报告
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
(1)在D中存在唯一的称为根的数据元素root;
(2)当n>1时,其余结点可分为m (m>0)个互不相交的有限集T1, T2, …, Tm,其中每一棵子集本身又是一棵符合本定义的树,称为根root的子树。
基本操作:
void insert(const char&);
void clear();
算法基本思想
{//建立叶子节点并入栈 PTR
i += N.CrtNode(PTR, &exp[i]);
}
else if (exp[i] == ' ')
i++;
else
{
switch (exp[i])
{
case '(': {
OPTR.push(exp[i]);
i++;
break; }
case ')':
{
op = OPTR.top(); OPTR.pop();
while (op != '(')
{
N. CrtSubTree(PTR, op);
op = OPTR.top(); OPTR.pop();
}
i++;break;
}
default: //exp[i]是 + - * /
while (!OPTR.empty())
{
op = OPTR.top();
if (Precede(op, exp[i]) == '>')
5建树过程中构造两个栈S1和S2,S1用来存放节点指针,S2用来存储操作符;遍历表达式时,如果遇到操作数,则建立节点并将其压入栈S1中。遇到操作符则将其压入操作符栈S2中,若栈顶还有操作符则弹出该操作符进行优先度比较,将优先度高的先放入栈中。弹出S2栈顶的操作符,建立节点,并弹出两个S1栈顶的节点,将操作符结点的左右指针域指向它们。直到操作符域为空。
请输入四则运算表达式:
2.输出形式
如果该中缀表达式正确,那么在字符界面上输出其后缀表达式和计算结果,其中后缀表达式中两相邻操作数之间利用空格隔开;如果不正确,在字符界面上输出表达式错误提示。具体格式:
后序表达式为:
最终结果为:
3.程序功能
该程序可以将用户输入的中缀表达式转换为后缀表达式并计算其结果
4.测试数据
while (op != '(')
{
N. CrtSubTree(PTR, op);
op = OPTR.top(); OPTR.pop();
}
i++;break;
}
default: //exp[i]是 + - * /
while (!OPTR.empty())
{
op = OPTR.top();
if (Precede(op, exp[i]) == '>')
int val();//返回结点的数值
void setLeft(Node* ) ; //设置左结点
void setRight(Node* );//设置右结点
Node* left()const;//返回左结点
Node* right()const;//返回右结点
③为了更快对二叉树中的元素进行插入和查找操作,使用二叉链表实现二叉树
bool push(const Elem&it);//插入元素操作
bool pop(const Elem&it);//删除操作
bool topValue(Elem&it);//获取栈顶元素的值
为了存储中缀表达式,构建一个树的ADT
数据对象D:D是具有相同特性的数据元素的集合
数据关系R:
若D为空集,则称为空树 。否则:
输入有误,请重新输入
5.请输入四则运算表达式:
EXIT
程序结束运行
二.概要设计
1.抽象数据类型
定义一个二叉树,用来存储用户输入的表达式。表达式通过定义一个栈来计算。
1为了访问二叉树中各节点的值,定义一个二叉树节点类,其ADT设计如下:
数据对象:用户输入的中缀表达式
数据关系:二叉树所对应的数据关系
基本操作:
Node *p1;//指向左子节点的指针
Node *p2;//指向右子节点的指针
public:
int val(){return data;};//返回结点的数值
void setLeft(Node*it){p1=it;}; //设置左结点
void setRight(Node*it){p2=it};//设置右结点
{//建立叶子节点并入栈 PTR
i += N.CrtNode(PTR, &exp[i]);
}
else if (exp[i] == ' ')
i++;
else
{
switch (exp[i])
{
case '(': {
OPTR.push(exp[i]);
i++;
break; }
case ')':
{
op = OPTR.top(); OPTR.pop();
{
N.CrtSubTree(PTR, op);
OPTR.pop();
}
if (exp[i] != '#')
{
OPTR.push(exp[i]);
i++;
}
break;
}
}
}//end else
}//end while
T = PTR.top();
PTR.pop();
}
};
2.算法具体步骤
4先将用户输入的中缀表达式存入一个二叉树中,然后对该二叉树进行一次后序遍历,即可得到该表达式的后序表达式,然后输出该后序表达式即可;
};
树的ADT设计。用树来存储中缀表达式
class Tree
{
private:
Node *root;
public:
Tree()
{
root = NULL;
}
~Tree(){ delete[]root; }
void insert(BiTree &T,char exp[])
{
//插入
stack <BiTree> PTR;//存放表达式树中的节点指针
Elem*listArray;//顺序表保存栈元素
public:
AStack(int sz)
{size=sz;top=0;listArray=newCar[sz];}//构造函数
~AStack(){delete []listArray;}//析构函数
void clear(){top=0;}//栈的清空
4.输入输出格式
输入:
char ch[100];//字符串数组存储表达式
while (i < 100)
{
scanf_s("%c", &c, 100);
ch[i++] = c;
}
输出:
T->PostOrderTraverse(T, exp, count);//输出后序遍历表达式
cout << "后序遍历表达式为:\n";
3求后缀表达式值时再构造一个栈S用来存放操作数。因为在定义数据类型的时候,要存储操作符,所以操作数也是用char类型存储的。后序遍历到操作数是需要将其转换为float型并压入栈中。
遍历到操作符时,栈顶两个操作数弹出,进行运算并将结果压入栈中。二叉树遍历完毕且栈中仅有一个元素,则计算完成,最后输出该结果即可。
item=listArray[-top];returntrue;
}
}//栈的删除
bool topValue(char& it) const
{
if(top==0)return false;
else
{it=listArray[top-1]; return true;}
}//获取栈顶元素
int length()const {return top;} //栈的长度
stack <char> OPTR;//存放操作符
char op;
Node N;
int i = 0;
OPTR.push('#');
op = OPTR.top();
while (!((exp[i] == '#') && (OPTR.top() == '#')))
{
if (IsDigital(exp[i]))
6求后缀表达式值时再构造一个栈S用来存放操作数。因为在定义 数据类型的时候,要存储操作符,所以操作数也是用char类型存储的。后序遍历到操作数是需要将其转换为float型并压入栈中。
遍历到操作符时,栈顶两个操作数弹出,进行运算并将结果压入栈中。二叉树遍历完毕且栈中仅有一个元素,则计算完成,最后输出该结果即可。
Node* left()const{return p1;};//返回左结点
Node* right()const{return p2;};//返回右结点
}
2栈的ADT设计:
class AStck:public Stack<char>//
{
private:
int size;//栈的长度
int top;//栈顶元素
HUNANUNIVERSITY
课程实验报告
题目:四则运算表达式求值
学生姓名:
学生学号:
专业班级:
ห้องสมุดไป่ตู้指导老师:
完成日期:
一.需求分析
1.输入形式
用户需输入一个中缀表达式,用户需输入四则运算符.括号和数字回车表示结束才,如:(3+4)*5/3。当用户输入错误的符号时,提示用户输入有误,并重新输入。具体格式:
树的构建部分伪代码:
class Tree
{
private:
Node *root;
public:
Tree()
{
root = NULL;
}
~Tree(){ delete[]root; }
void insert(BiTree &T,char exp[])
{
//插入
stack <BiTree> PTR;//存放表达式树中的节点指针
1.请输入四则运算表达式:
21+23*(12-6)
后缀表达式为:
21 23 12 6 -*+
计算结果是159
2.请输入四则运算表达式:
4/5+4-5
后缀表达式为:
4 5 / 4 + 5 -
计算结果是-0.2
3.请输入四则运算表达式:
1.5+4/5
输入有误,请重新输入
4.请输入四则元素表达式:
21^7%y*4
4为了计算中缀表达式的值,通过定义一个栈来计算。栈的ADT设计如下:
数据对象:D={ ai| ai∈ElemSet, i=1,2,...,n, n≥0 }
数据关系:R1={ <ai-1, ai>| ai-1, ai∈D, i=2,...,n }
(约定an端为栈顶,a1端为栈底。)
基本操作:
void clear();//初始化操作
1先将用户输入的中缀表达式存入一个二叉树中,然后对该二叉树进行一次后序遍历,即可得到该表达式的后序表达式,然后输出该后序表达式即可;
2建树过程中构造两个栈S1和S2,S1用来存放节点指针,S2用来存储操作符;遍历表达式时,如果遇到操作数,则建立节点并将其压入栈S1中。遇到操作符则将其压入操作符栈S2中,若栈顶还有操作符则弹出该操作符进行优先度比较,将优先度高的先放入栈中。弹出S2栈顶的操作符,建立节点,并弹出两个S1栈顶的节点,将操作符结点的左右指针域指向它们。直到操作符域为空。
for (i = 0; i < count; i++)
cout << exp[i];
请输入一个四则运算表达式:
21+23*(12-6)
该表达式的后缀表达式为:
21 23 12 6 -*+
运算结果为:
159
5.函数调用关系
创建节点
创建二叉树
连接节点
主程序后序遍历输出二叉树
符数转换
表达式的计算优先级判断
{
N.CrtSubTree(PTR, op);
OPTR.pop();
}
if (exp[i] != '#')
{
OPTR.push(exp[i]);
i++;
}
break;
}
}
}//end else
}//end while
T = PTR.top();
PTR.pop();
}
};
3.算法时空分析
用户输入的表达式存入二叉树的时间复杂度为Ɵ(n),对二叉树的后序遍历的时间复杂度也是Ɵ(n),运算的时间复杂度也是Ɵ(n)。所以总的时间复杂度是Ɵ(n)。
2.程序基本流程
本程序主要分四个模块:
输入模块:用户输入一个正确的中缀表达式,若输入错误,提示输入有误并重新输入;
转换模块:将中缀表达式转换为后缀表达式;
计算模块:计算该中缀表达式的值;
输出模块:输出后缀表达式及其结果。
三.详细设计
1.物理数据类型
1二叉树节点类定义:
class Node
{
private:
bool push(constchar&item)
{
if(top==size)return false;
else
{listArray[top++]=item; return true; }
}//栈的插入
bool pop(char& item)
{
if(top==0)return false;
else
{
四.调试分析
stack <char> OPTR;//存放操作符
char op;
Node N;
int i = 0;
OPTR.push('#');
op = OPTR.top();
while (!((exp[i] == '#') && (OPTR.top() == '#')))
{
if (IsDigital(exp[i]))
(2)当n>1时,其余结点可分为m (m>0)个互不相交的有限集T1, T2, …, Tm,其中每一棵子集本身又是一棵符合本定义的树,称为根root的子树。
基本操作:
void insert(const char&);
void clear();
算法基本思想
{//建立叶子节点并入栈 PTR
i += N.CrtNode(PTR, &exp[i]);
}
else if (exp[i] == ' ')
i++;
else
{
switch (exp[i])
{
case '(': {
OPTR.push(exp[i]);
i++;
break; }
case ')':
{
op = OPTR.top(); OPTR.pop();
while (op != '(')
{
N. CrtSubTree(PTR, op);
op = OPTR.top(); OPTR.pop();
}
i++;break;
}
default: //exp[i]是 + - * /
while (!OPTR.empty())
{
op = OPTR.top();
if (Precede(op, exp[i]) == '>')
5建树过程中构造两个栈S1和S2,S1用来存放节点指针,S2用来存储操作符;遍历表达式时,如果遇到操作数,则建立节点并将其压入栈S1中。遇到操作符则将其压入操作符栈S2中,若栈顶还有操作符则弹出该操作符进行优先度比较,将优先度高的先放入栈中。弹出S2栈顶的操作符,建立节点,并弹出两个S1栈顶的节点,将操作符结点的左右指针域指向它们。直到操作符域为空。
请输入四则运算表达式:
2.输出形式
如果该中缀表达式正确,那么在字符界面上输出其后缀表达式和计算结果,其中后缀表达式中两相邻操作数之间利用空格隔开;如果不正确,在字符界面上输出表达式错误提示。具体格式:
后序表达式为:
最终结果为:
3.程序功能
该程序可以将用户输入的中缀表达式转换为后缀表达式并计算其结果
4.测试数据
while (op != '(')
{
N. CrtSubTree(PTR, op);
op = OPTR.top(); OPTR.pop();
}
i++;break;
}
default: //exp[i]是 + - * /
while (!OPTR.empty())
{
op = OPTR.top();
if (Precede(op, exp[i]) == '>')
int val();//返回结点的数值
void setLeft(Node* ) ; //设置左结点
void setRight(Node* );//设置右结点
Node* left()const;//返回左结点
Node* right()const;//返回右结点
③为了更快对二叉树中的元素进行插入和查找操作,使用二叉链表实现二叉树
bool push(const Elem&it);//插入元素操作
bool pop(const Elem&it);//删除操作
bool topValue(Elem&it);//获取栈顶元素的值
为了存储中缀表达式,构建一个树的ADT
数据对象D:D是具有相同特性的数据元素的集合
数据关系R:
若D为空集,则称为空树 。否则:
输入有误,请重新输入
5.请输入四则运算表达式:
EXIT
程序结束运行
二.概要设计
1.抽象数据类型
定义一个二叉树,用来存储用户输入的表达式。表达式通过定义一个栈来计算。
1为了访问二叉树中各节点的值,定义一个二叉树节点类,其ADT设计如下:
数据对象:用户输入的中缀表达式
数据关系:二叉树所对应的数据关系
基本操作:
Node *p1;//指向左子节点的指针
Node *p2;//指向右子节点的指针
public:
int val(){return data;};//返回结点的数值
void setLeft(Node*it){p1=it;}; //设置左结点
void setRight(Node*it){p2=it};//设置右结点
{//建立叶子节点并入栈 PTR
i += N.CrtNode(PTR, &exp[i]);
}
else if (exp[i] == ' ')
i++;
else
{
switch (exp[i])
{
case '(': {
OPTR.push(exp[i]);
i++;
break; }
case ')':
{
op = OPTR.top(); OPTR.pop();
{
N.CrtSubTree(PTR, op);
OPTR.pop();
}
if (exp[i] != '#')
{
OPTR.push(exp[i]);
i++;
}
break;
}
}
}//end else
}//end while
T = PTR.top();
PTR.pop();
}
};
2.算法具体步骤
4先将用户输入的中缀表达式存入一个二叉树中,然后对该二叉树进行一次后序遍历,即可得到该表达式的后序表达式,然后输出该后序表达式即可;
};
树的ADT设计。用树来存储中缀表达式
class Tree
{
private:
Node *root;
public:
Tree()
{
root = NULL;
}
~Tree(){ delete[]root; }
void insert(BiTree &T,char exp[])
{
//插入
stack <BiTree> PTR;//存放表达式树中的节点指针
Elem*listArray;//顺序表保存栈元素
public:
AStack(int sz)
{size=sz;top=0;listArray=newCar[sz];}//构造函数
~AStack(){delete []listArray;}//析构函数
void clear(){top=0;}//栈的清空
4.输入输出格式
输入:
char ch[100];//字符串数组存储表达式
while (i < 100)
{
scanf_s("%c", &c, 100);
ch[i++] = c;
}
输出:
T->PostOrderTraverse(T, exp, count);//输出后序遍历表达式
cout << "后序遍历表达式为:\n";
3求后缀表达式值时再构造一个栈S用来存放操作数。因为在定义数据类型的时候,要存储操作符,所以操作数也是用char类型存储的。后序遍历到操作数是需要将其转换为float型并压入栈中。
遍历到操作符时,栈顶两个操作数弹出,进行运算并将结果压入栈中。二叉树遍历完毕且栈中仅有一个元素,则计算完成,最后输出该结果即可。
item=listArray[-top];returntrue;
}
}//栈的删除
bool topValue(char& it) const
{
if(top==0)return false;
else
{it=listArray[top-1]; return true;}
}//获取栈顶元素
int length()const {return top;} //栈的长度
stack <char> OPTR;//存放操作符
char op;
Node N;
int i = 0;
OPTR.push('#');
op = OPTR.top();
while (!((exp[i] == '#') && (OPTR.top() == '#')))
{
if (IsDigital(exp[i]))
6求后缀表达式值时再构造一个栈S用来存放操作数。因为在定义 数据类型的时候,要存储操作符,所以操作数也是用char类型存储的。后序遍历到操作数是需要将其转换为float型并压入栈中。
遍历到操作符时,栈顶两个操作数弹出,进行运算并将结果压入栈中。二叉树遍历完毕且栈中仅有一个元素,则计算完成,最后输出该结果即可。
Node* left()const{return p1;};//返回左结点
Node* right()const{return p2;};//返回右结点
}
2栈的ADT设计:
class AStck:public Stack<char>//
{
private:
int size;//栈的长度
int top;//栈顶元素
HUNANUNIVERSITY
课程实验报告
题目:四则运算表达式求值
学生姓名:
学生学号:
专业班级:
ห้องสมุดไป่ตู้指导老师:
完成日期:
一.需求分析
1.输入形式
用户需输入一个中缀表达式,用户需输入四则运算符.括号和数字回车表示结束才,如:(3+4)*5/3。当用户输入错误的符号时,提示用户输入有误,并重新输入。具体格式:
树的构建部分伪代码:
class Tree
{
private:
Node *root;
public:
Tree()
{
root = NULL;
}
~Tree(){ delete[]root; }
void insert(BiTree &T,char exp[])
{
//插入
stack <BiTree> PTR;//存放表达式树中的节点指针
1.请输入四则运算表达式:
21+23*(12-6)
后缀表达式为:
21 23 12 6 -*+
计算结果是159
2.请输入四则运算表达式:
4/5+4-5
后缀表达式为:
4 5 / 4 + 5 -
计算结果是-0.2
3.请输入四则运算表达式:
1.5+4/5
输入有误,请重新输入
4.请输入四则元素表达式:
21^7%y*4
4为了计算中缀表达式的值,通过定义一个栈来计算。栈的ADT设计如下:
数据对象:D={ ai| ai∈ElemSet, i=1,2,...,n, n≥0 }
数据关系:R1={ <ai-1, ai>| ai-1, ai∈D, i=2,...,n }
(约定an端为栈顶,a1端为栈底。)
基本操作:
void clear();//初始化操作
1先将用户输入的中缀表达式存入一个二叉树中,然后对该二叉树进行一次后序遍历,即可得到该表达式的后序表达式,然后输出该后序表达式即可;
2建树过程中构造两个栈S1和S2,S1用来存放节点指针,S2用来存储操作符;遍历表达式时,如果遇到操作数,则建立节点并将其压入栈S1中。遇到操作符则将其压入操作符栈S2中,若栈顶还有操作符则弹出该操作符进行优先度比较,将优先度高的先放入栈中。弹出S2栈顶的操作符,建立节点,并弹出两个S1栈顶的节点,将操作符结点的左右指针域指向它们。直到操作符域为空。
for (i = 0; i < count; i++)
cout << exp[i];
请输入一个四则运算表达式:
21+23*(12-6)
该表达式的后缀表达式为:
21 23 12 6 -*+
运算结果为:
159
5.函数调用关系
创建节点
创建二叉树
连接节点
主程序后序遍历输出二叉树
符数转换
表达式的计算优先级判断
{
N.CrtSubTree(PTR, op);
OPTR.pop();
}
if (exp[i] != '#')
{
OPTR.push(exp[i]);
i++;
}
break;
}
}
}//end else
}//end while
T = PTR.top();
PTR.pop();
}
};
3.算法时空分析
用户输入的表达式存入二叉树的时间复杂度为Ɵ(n),对二叉树的后序遍历的时间复杂度也是Ɵ(n),运算的时间复杂度也是Ɵ(n)。所以总的时间复杂度是Ɵ(n)。
2.程序基本流程
本程序主要分四个模块:
输入模块:用户输入一个正确的中缀表达式,若输入错误,提示输入有误并重新输入;
转换模块:将中缀表达式转换为后缀表达式;
计算模块:计算该中缀表达式的值;
输出模块:输出后缀表达式及其结果。
三.详细设计
1.物理数据类型
1二叉树节点类定义:
class Node
{
private:
bool push(constchar&item)
{
if(top==size)return false;
else
{listArray[top++]=item; return true; }
}//栈的插入
bool pop(char& item)
{
if(top==0)return false;
else
{
四.调试分析
stack <char> OPTR;//存放操作符
char op;
Node N;
int i = 0;
OPTR.push('#');
op = OPTR.top();
while (!((exp[i] == '#') && (OPTR.top() == '#')))
{
if (IsDigital(exp[i]))