关于表达式(数据结构)的问题

cglee 2002-08-30 12:20:00
请问再考虑表达式的问题(如计算值等)时,什么时候使用栈结构方便?什么时候使用二叉树结构方便?
...全文
70 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
alidiedie 2002-09-04
  • 打赏
  • 举报
回复
不管是前缀还是后缀,都可以用栈也可以用树.
若是后缀的话,只用一个存放操作数的栈即可.
中缀(一般见到的),要用两个栈,操作数栈和操作符栈,如果没有定义操作符的优先级表,还要有一个存放操作符优先级的栈.
树也可以计算中缀或后缀,分别对应中序遍历和后序遍历.

我感觉用树比栈麻烦,要建一棵树也是比较麻烦的.
三色 2002-09-04
  • 打赏
  • 举报
回复
由于内容太长,不能在一个贴子内发表,
所以以上两篇贴子是一个整体,编译时应放在一起。
如有什么问题,请留下你的Email或发Email给我。
三色 2002-09-04
  • 打赏
  • 举报
回复
续上文中的头文件fx.h
//----------------------------------------------------------------
int DoNum(char format)
{
double NowNum=0;
if(flag==-1){NumStack.push(double(format-'0'));flag=0;}
else if(flag==0)
{
double NowNum=NumStack.pop();
NowNum=NowNum*10+double(format-'0');
NumStack.push(NowNum);
}
else
{
NowNum=NumStack.pop();
NowNum=NowNum+pow(0.1,flag++)*double(format-'0');
NumStack.push(NowNum);
}
return 0;
}
//-----------------------------------------------------
bool FuncOver(char *format,int i)
{
switch(format[i])
{
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
case '.': case '+': case '-': case '*': case '/':
case '^': case '~': case '(': case ')':
return true;break;
default : return false;break;
}
}
//-----------------------------------------------------
int DoFunction(char *Func)
{
struct stack F;
F.value=FUNC;
if(stricmp(Func,"sin")==0)
F.sign='s';
else if(stricmp(Func,"cos")==0)
F.sign='c';
else if(stricmp(Func,"tan")==0)
F.sign='t';
else if(stricmp(Func,"cot")==0)
F.sign='C';
else if(stricmp(Func,"exp")==0)
F.sign='e';
else if(stricmp(Func,"abs")==0)
F.sign='a';
else if(stricmp(Func,"lg")==0)
F.sign='l';
else if(stricmp(Func,"ln")==0)
F.sign='L';
else if(stricmp(Func,"sqrt")==0)
F.sign='S';
else return 0;
while(!OpeStack.empty())
{
struct stack p=OpeStack.get();
if(p.value>=F.value)
{
dealwith(p.sign);
OpeStack.pop();
}
else break;
}
OpeStack.push(F);
return 0;
}
//-----------------------------------------------------
double f(char *format,double x)
{
int i,FuncNum=0;
char Func[10];
for(i=0;*(format+i)!='\0';i++)
{
switch(*(format+i))
{
case 'x':
case 'X':
if(format[i-1]=='e'||format[i-1]=='E')
{ Func[FuncNum++]=*(format+i);
Func[FuncNum]='\0';
if(FuncOver(format,i+1)==true)
{
DoFunction(Func);
FuncNum=0;
flag=-1;
}}
else NumStack.push(x);flag=-1;
continue;
case '+':
case '-':if(i==0||format[i-1]=='(')NumStack.push(0);
case '*':
case '/':
case '^':
case '(':
case ')':DoOpe(*(format+i));flag=-1;continue;
case '.':flag=1;continue;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':DoNum(*(format+i));continue;
case 'a': case 'b': case 'c': case 'd':
case 'e': case 'f': case 'g': case 'h':
case 'i': case 'j': case 'k': case 'l':
case 'm': case 'n': case 'o': case 'p':
case 'q': case 'r': case 's': case 't':
case 'u': case 'v': case 'w': case 'y'://没有x
case 'z':
case 'A': case 'B': case 'C': case 'D':
case 'E': case 'F': case 'G': case 'H':
case 'I': case 'J': case 'K': case 'L':
case 'M': case 'N': case 'O': case 'P':
case 'Q': case 'R': case 'S': case 'T':
case 'U': case 'V': case 'W': case 'Y'://没有X
case 'Z':
Func[FuncNum++]=*(format+i);
Func[FuncNum]='\0';
if(FuncOver(format,i+1)==true)
{
DoFunction(Func);
FuncNum=0;
flag=-1;
}
continue;
default :continue;
}
}
solvestack('=');
double aa=NumStack.get();
NumStack.clear();
OpeStack.clear();
flag=-1;
return aa;
}
//-------以下函数df(char *format,double x)用于求函数表达式为
//-------format在x点的导数值.
double df(char *format,double x)
{
double h=1e-6;
double x0=x,x1=x+h,x2=x+h*2;
return (-3*f(format,x0)+4*f(format,x1)-f(format,x2))/2/h;

}
//------------------------------------------------------
三色 2002-09-04
  • 打赏
  • 举报
回复
我用c++写的一段源程序,用于求表达式的值。
主要函数是:double f(char *format,double x)
format 是一串字符,如sin(ln(x*x+1)+1)+1;x 是自变量的值函数返回表达式的值。我用的是栈结构,在C++Builder5和VC++6上编译通过。

比如fx.cpp如下:

#include "fx.h"
#include "iostream.h"
void main()
{
double x=2,y;
y=f("sin(ln(x*x+1)+1)+1",x);
cout<<y<<endl;
}
//----------------------------------------------------------------

fx.h的内容如下:

//三色 2002.8.12 修改.
//本文件的"核心"函数:f(char *format,double x)用于求
//表达式为format的函数在自变量为x时的值.
//在C++Builder5上编译通过.
#include "iostream.h"
#include "math.h"
#include "string.h"
#define EPS 1e-20
//-------------------------------------
#define ADD 1
#define SUB 1
#define MUL 2
#define DIV 2
#define INV 3
#define PAR 0
#define KAI 3
#define FAC 0
#define FUNC 4
//-----------------------------------
#include "math.h"
#define YES 1
#define NO 0
//--------------------------------------
#define DEG 1
#define RAD 2
#define GRAD 3
//-------------------------------
int test=0;
//-----------------------------------------------------------------
class NS
{public:
int n;
double a[100];
NS(){n=0;}
double get(){return a[n-1];}
double pop(){return a[--n];}
void push(double x){a[n++]=x;}
bool empty(){return n<=0?true:false;}
void clear(){n=0;}
}NumStack;
struct stack
{char sign;
char value;
};
class OP
{public:
int n;
struct stack a[100];
OP(){n=0;}
struct stack get(){return *(a+n-1);}
struct stack pop(){return *(a+--n);}
void push(struct stack x){a[n].sign=x.sign;a[n].value=x.value;n++;}
bool empty(){return n<=0?true:false;}
void clear(){n=0;;}
}OpeStack;
//--------------------------------------------------
int flag=-1;
////
double dealwith(char ch)
{
double i,j;
i=NumStack.pop();
switch(ch)
{
case '+': j=NumStack.pop();NumStack.push(j+i);break;
case '-': j=NumStack.pop();NumStack.push(j-i);break;
case '*': j=NumStack.pop();NumStack.push(j*i);break;
case '/':
j=NumStack.pop();
if(i!=0)NumStack.push(j/i);
else
cout<<"除数不能为零!!!\n";
break;
case '^': j=NumStack.pop();NumStack.push(pow(j,i));break;
case '~': j=NumStack.pop();NumStack.push(pow(j,1.0/i));break;
case 's': NumStack.push(sin(i));break;
case 'c': NumStack.push(cos(i));break;
case 't': NumStack.push(tan(i));break;
case 'C': NumStack.push(1/tan(i));break;
case 'e': NumStack.push(exp(i));break;
case 'l': NumStack.push(log10(i));break;
case 'L': NumStack.push(log(i));break;
case 'a': NumStack.push(fabs(i));break;
case 'S': NumStack.push(sqrt(i));break;
default :break;
}
return NumStack.get();
}
//----------------------------------------------------
void solvestack(char ch)
{
if(ch==')'){
struct stack p=OpeStack.pop();
while(p.sign!='('){
dealwith(p.sign);
p=OpeStack.pop();}}
else if(ch=='='){
struct stack p=OpeStack.get();
while(!OpeStack.empty()){
p=OpeStack.pop();
dealwith(p.sign);}}
flag=-1;
}
//--------------------------------------------------
int DoOpe(char format)
{
struct stack p,q;
switch(format)
{
case '+':q.sign='+';q.value=ADD;break;
case '-':q.sign='-';q.value=SUB;break;
case '*':q.sign='*';q.value=MUL;break;
case '/':q.sign='/';q.value=DIV;break;
case '^':q.sign='^';q.value=KAI;break;
case '(':
q.sign='(';
q.value=PAR;
OpeStack.push(q);
flag=-1;
return 0;
case ')':
q.sign=')';
q.value=PAR;
solvestack(')');
return 0;
default :;
}
while(!OpeStack.empty())
{
p=OpeStack.get();
if(p.value>=q.value)
{
dealwith(p.sign);
OpeStack.pop();
}
else break;
}
OpeStack.push(q);
return 0;
}
cglee 2002-09-02
  • 打赏
  • 举报
回复
GZ是什么意思?
cglee 2002-09-02
  • 打赏
  • 举报
回复
好的,我想看一下你是怎样写的,我们可以讨论讨论
三色 2002-09-02
  • 打赏
  • 举报
回复
我用c++写的一段源程序,用于求表达式的值。
主要函数是:double f(char *format,double x)
//format 是一串字符,如sin(ln(x*x+1)+1)+1;
//x 是自变量的值;
//函数返回表达式的值。
我用的是栈结构,在C++Builder上编译通过。如果想要的话我下次上网时贴一下。
djniulihao 2002-09-01
  • 打赏
  • 举报
回复
GZ
cglee 2002-08-30
  • 打赏
  • 举报
回复
不管是前缀还是后缀,采用什么结构都应该是可以的吧。

栈结构是根据要进栈的运算符和栈顶的运算符比较优先级,已确定是否对操作数的栈顶元素进行运算;表达式基于二叉树结构来表示,则按后序遍历的递归算法对表达式求值即可。

但我不明白,采用那种结构会更好,或效率更高,有谁能从较高的层次上分析一下。
谢谢!
ShallowShrimp 2002-08-30
  • 打赏
  • 举报
回复
栈结构主要是针对后辍表达式,树状结构主要是针对中辍表达式。

后辍表达式的符号是堆叠在一起的,所以宜采用栈结构来处理。
而树状组织结构比较符合中辍表达式。
cglee 2002-08-30
  • 打赏
  • 举报
回复
就说表达式求值的问题吧,表达式中可有参数。
在数据结构中,有用栈结构求表达式值的算法,在树一章中,又讲了可用二叉树表示表达式。那么,我想知道,用这两种结构解决表达式求值的问题时,各有什么方便和不足。
zhf0021 2002-08-30
  • 打赏
  • 举报
回复
能否具体一些

33,008

社区成员

发帖
与我相关
我的任务
社区描述
数据结构与算法相关内容讨论专区
社区管理员
  • 数据结构与算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧