}
Expression&Postfix()//将中缀表达式转变为后缀表达式
{
First();
if(Get()->type==POSTFIX)return*this;
Stacks;s.Push('=');
Expressiontemp;
ExpNode*p=Next();
while(p!
=NULL)
{
switch(p->type)
{
caseOPND:
temp.LastInsert(*p);p=Next();break;
caseOPTR:
while(isp(s.GetTop())>icp(p->optr))
{
ExpNodenewoptr(s.Pop());
temp.LastInsert(newoptr);
}
if(isp(s.GetTop())==icp(p->optr))
{
s.Pop();p=Next();break;
}
s.Push(p->optr);p=Next();break;
default:
break;
}
}
*this=temp;
pGetFirst()->data.type=POSTFIX;
return*this;
}
TypeCalculate()
{
Expressiontemp=*this;
if(pGetFirst()->data.type!
=POSTFIX)temp.Postfix();
Stacks;Typeleft,right;
for(ExpNode*p=temp.Next();p!
=NULL;p=temp.Next())
{
switch(p->type)
{
caseOPND:
s.Push(p->opnd);break;
caseOPTR:
right=s.Pop();left=s.Pop();
switch(p->optr)
{
case'+':
s.Push(left+right);break;
case'-':
s.Push(left-right);break;
case'*':
s.Push(left*right);break;
case'/':
if(right!
=0)s.Push(left/right);elsereturn0;break;
//case'%':
if(right!
=0)s.Push(left%right);elsereturn0;break;
//case'^':
s.Push(Power(left,right));break;
default:
break;
}
default:
break;
}
}
returns.Pop();
}
private:
intisp(charoptr)
{
switch(optr)
{
case'=':
return0;
case'(':
return1;
case'^':
return7;
case'*':
return5;
case'/':
return5;
case'%':
return5;
case'+':
return3;
case'-':
return3;
case')':
return8;
default:
return0;
}
}
inticp(charoptr)
{
switch(optr)
{
case'=':
return0;
case'(':
return8;
case'^':
return6;
case'*':
return4;
case'/':
return4;
case'%':
return4;
case'+':
return2;
case'-':
return2;
case')':
return1;
default:
return0;
}
}
};
#endif
几点说明
1、表达式用单链表储存,你可以看到这个链表中既有操作数又有操作符,假如你看过我的《如何在一个链表中链入不同类型的对象》,这里的方法也是对那篇文章的补充。
2、输入表达式时,会将原来的内容清空,并且必须按照中缀表示输入。
假如你细看一下中缀表达式,你就会发现,除了括号,表达式的结构是“操作数”、“操作符”、“操作数”、……“操作符(=)”,为了统一这个规律,同时也为了使输入函数简单一点,规定括号必须这样输入“0(”、“)0”;这样一来,“0”就不能作为操作数出现在表达式中了。
因为我没有在输入函数中增加容错的语句,所以一旦输错了,那程序就“死”了。
3、表达式求值的过程是,先变成后缀表示,然后用后缀表示求值。
因为原书讲解的是这两个算法,并且用这两个算法就能完成中缀表达式的求值,所以我就没写中缀表达式的直接求值算法。
具体算法说明参见原书,我就不废话了。
4、Calculate()注释掉的两行,“%”是因为只对整型表达式合法,“^”的Power()函数没有完成。
5、isp(),icp()的返回值,原书说的不细,我来多说两句。
‘=’(表达式开始和结束标志)的栈内栈外优先级都是最低。
‘(’栈外最高,栈内次最低。
‘)’栈外次最低,不进栈。
‘^’栈内次最高,栈外比栈内低。
‘×÷%’栈内比‘^’栈外低,栈外比栈内低。
‘+-’栈内比‘×’栈外低,栈外比栈内低。
这样,综合起来,就有9个优先级,于是就得出了书上的那个表。
更多内容请看数据结构数据结构教程数据结构相关文章专题,或队列应用
我看的两本教科书(《数据结构(C语言版)》还有这本黄皮书)都是以这个讲解队列应用的,而且都是银行营业模拟(太没新意了)。
细比较,这两本书模拟的银行营业的方式还是不同的。
--framecontents-->
--/framecontents-->
1997版的《数据结构(C语言版)》的银行还是老式的营业模式(究竟是1997年的事了),现在的很多地方还是这种营业模式——几个窗口同时排队。
这种方式其实不太合理,经常会出现先来的还没有后来的先办理业务(经常前面一个人磨磨蹭蹭,别的队越来越短,让你恨不得把前面那人干掉)。
1999版的这本黄皮书的银行改成了一种挂牌的营业方式,每个来到的顾客发一个号码,假如哪个柜台空闲了,就叫号码最靠前的顾客来办理业务;假如同时几个柜台空闲,就按照一种法则来决定这几个柜台叫号的顺序(最简单的是按柜台号码顺序)。
这样,就能保证顾客按照先来后到的顺序接受服务——因为大家排在一个队里。
这样的营业模式我在北京的西直门工商银行见过,应该说这是比较合理的一种营业模式。
不过,在本文中最重要的是,这样的营业模式比较好模拟(一个队列总比N个队列好操作)。
原书的这部分太难看了,我看的晕晕的,我也不知道按照原书的方法能不能做出来,因为我没看懂(旁白:
靠,你小子这样还来现眼)。
我按照实际情况模拟,实现如下:
#ifndefSimulation_H
#defineSimulation_H
#include
#include
#include
classTeller
{
public:
inttotalCustomerCount;
inttotalServiceTime;
intfinishServiceTime;
Teller():
totalCustomerCount(0),totalServiceTime(0),
finishServiceTime(0){}
};
//#definePRINTPROCESS
classSimulation
{
public:
Simulation()
{
cout< cout<<"柜台数量:
";cin>>tellerNum;
cout<<"营业时间:
";cin>>simuTime;
cout<<"两个顾客来到的最小间隔时间:
";cin>>arrivalLow;
cout<<"两个顾客来到的最大间隔时间:
";cin>>arrivalHigh;
cout<<"柜台服务最短时间:
";cin>>serviceLow;
cout<<"柜台服务最长时间:
";cin>>serviceHigh;
arrivalRange=arrivalHigh-arrivalLow+1;
serviceRange=serviceHigh-serviceLow+1;
srand((unsigned)time(NULL));
}
Simulation(inttellerNum,intsimuTime,intarrivalLow,intarrivalHigh,intserviceLow,intserviceHigh)
:
tellerNum(tellerNum),simuTime(simuTime),arrivalLow(arrivalLow),arrivalHigh(arrivalHigh),
serviceLow(serviceLow),serviceHigh(serviceHigh),
arrivalRange(arrivalHigh-arrivalLow+1),serviceRange(serviceHigh-serviceLow+1)
{srand((unsigned)time(NULL));}
voidInitialize()
{
curTime=nextTime=0;
customerNum=customerTime=0;
for(inti=1;i<=tellerNum;i++)
{
tellers[i].totalCustomerCount=0;
tellers[i].totalServiceTime=0;
tellers[i].finishServiceTime=0;
}
customer.MakeEmpty();
}
voidRun()
{
Initialize();
NextArrived();
#ifdefPRINTPROCESS
cout< cout<<"tellerID";
for(intk=1;k<=tellerNum;k++)cout<<"TELLER"< cout< #endif
for(curTime=0;curTime<=simuTime;curTime++)
{
if(curTime>=nextTime)
{
CustomerArrived();
NextArrived();
}
#ifdefPRINTPROCESS
cout<<"Time:
"< #endif
for(inti=1;i<=tellerNum;i++)
{
if(tellers[i].finishServiceTime if(tellers[i].finishServiceTime==curTime&&!
customer.IsEmpty())
{
intt=NextService();
#ifdefPRINTPROCESS
cout<<''< #endif
CustomerDeparture();
tellers[i].totalCustomerCount++;
tellers[i].totalServiceTime+=t;
tellers[i].finishServiceTime+=t;
}
#ifdefPRINTPROCESS
elsecout<<"";
#endif
}
#ifdefPRINTPROCESS
cout< #endif
}
PrintResult();
}
voidPtintSimuPara()
{
cout< cout<<"柜台数量:
"<"< cout<<"两个顾客来到的最小间隔时间:
"< cout<<"两个顾客来到的最大间隔时间:
"< cout<<"柜台服务最短时间:
"< cout<<"柜台服务最长时间:
"< }
voidPrintResult()
{
inttSN=0;
longtST=0;
cout< cout<<"-------------模拟结果-------------------";
cout<