![數(shù)據(jù)結(jié)構(gòu)輔導(dǎo)棧和隊(duì)列_第1頁(yè)](http://file4.renrendoc.com/view2/M03/01/14/wKhkFmaU1mmAGWuYAAJk9dMAnLo576.jpg)
![數(shù)據(jù)結(jié)構(gòu)輔導(dǎo)棧和隊(duì)列_第2頁(yè)](http://file4.renrendoc.com/view2/M03/01/14/wKhkFmaU1mmAGWuYAAJk9dMAnLo5762.jpg)
![數(shù)據(jù)結(jié)構(gòu)輔導(dǎo)棧和隊(duì)列_第3頁(yè)](http://file4.renrendoc.com/view2/M03/01/14/wKhkFmaU1mmAGWuYAAJk9dMAnLo5763.jpg)
![數(shù)據(jù)結(jié)構(gòu)輔導(dǎo)棧和隊(duì)列_第4頁(yè)](http://file4.renrendoc.com/view2/M03/01/14/wKhkFmaU1mmAGWuYAAJk9dMAnLo5764.jpg)
![數(shù)據(jù)結(jié)構(gòu)輔導(dǎo)棧和隊(duì)列_第5頁(yè)](http://file4.renrendoc.com/view2/M03/01/14/wKhkFmaU1mmAGWuYAAJk9dMAnLo5765.jpg)
版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
數(shù)據(jù)結(jié)構(gòu)輔導(dǎo)棧和隊(duì)列1
一、棧
1.棧的定義
棧(Stack)又稱堆棧,它是一種運(yùn)算受限的線性表,其限制是僅答應(yīng)在表的
一端進(jìn)行插入和刪除運(yùn)算。人們把此端稱為棧頂,棧頂?shù)牡谝粋€(gè)元素被稱為棧
頂元素,相對(duì)地,把另一端稱為棧底。向一個(gè)棧插入新元素又稱為進(jìn)?;蛉?/p>
棧,它是把該元素放到棧頂元素的上面,使之成為新的棧頂元素;從一個(gè)棧刪
除元素又稱為出?;蛲藯?,它是把棧頂元素刪除掉,使其下面的相鄰元素成為
新的棧頂元素。
在日常生活中,有許多類似棧的例子,如刷洗盤子時(shí),依次把每個(gè)洗凈的
盤子放到洗好的盤子上,相當(dāng)于進(jìn)棧;取用盤子時(shí),從一摞盤子上一個(gè)接一個(gè)
地向下拿,相當(dāng)于出棧。又如向槍支彈夾里裝子彈時(shí),子彈被一個(gè)接一個(gè)地壓
入,則為進(jìn)棧;射擊時(shí)子彈總是從頂部一個(gè)接一個(gè)地被射出,此為子彈出棧。
由于棧的插入和刪除運(yùn)算僅在棧頂一端進(jìn)行,后進(jìn)棧的元素必定先出棧,
所以又把棧稱為后進(jìn)先出表(LastInFirstOut,簡(jiǎn)稱LIFO)。
例如,假定一個(gè)棧S為(a,b,c),其中字符c的一端為棧頂,字符c為棧頂
元素。若向S壓入一個(gè)元素d,則S變?yōu)?a,b,c,d),此時(shí)字符d為棧頂元素;
若接著從棧S中依次刪除兩個(gè)元素,則首先刪除的是元素d,接著刪除的使元
素c,棧S變?yōu)?a,b),棧頂元素為b。
視頻教程'css.shtml'target』_blank'title=,div視頻教程'div2.棧的
存儲(chǔ)結(jié)構(gòu)
棧既然是一種線性表,所以線性表的順序存儲(chǔ)和鏈接存儲(chǔ)結(jié)構(gòu)同樣適用于
棧。
(1)棧的順序存儲(chǔ)結(jié)構(gòu)
棧的順序存儲(chǔ)結(jié)構(gòu)同樣需要使用一個(gè)數(shù)組和一個(gè)整型變量來(lái)實(shí)現(xiàn),利用數(shù)
組來(lái)順序存儲(chǔ)棧中的所有元素,利用整型變量來(lái)存儲(chǔ)棧頂元素的下標(biāo)位置。假
定棧數(shù)組用stack[StackMaxSize]表示,指示棧頂位置的整型變量用top表
示,則元素類型為ElemType的棧的順序存儲(chǔ)類型可定義為:
ElemTypestack[StackMaxSize];
inttop;
其中,StackMaxSize為一個(gè)整型全局常量,需事先通過(guò)const語(yǔ)句定義,
由它確定順序棧(即順序存儲(chǔ)的棧)的最大深度,又稱為長(zhǎng)度,即棧最多能夠存
儲(chǔ)的元素個(gè)數(shù);由于top用來(lái)指示棧頂元素的位置,所以把它稱為棧頂指針。
棧的順序存儲(chǔ)結(jié)構(gòu)同樣可以定義在一個(gè)記錄類型中,假定該記錄類型用
Stack表示,則定義為:
structStack{
ElemTypestack[StackMaxSize];
inttop;
);
在順序存儲(chǔ)的棧中,top的值為T表示??眨看蜗驐V袎喝胍粋€(gè)元素
時(shí),首先使top增1,用以指示新的棧頂位置,然后再把元素賦值到這個(gè)位置
上,每次從棧中彈出一個(gè)元素時(shí),首先取出棧頂元素,然后使top減1,指示
前一個(gè)元素成為新的棧頂元素。由此可知,對(duì)順序棧的插入和刪除運(yùn)算相當(dāng)于
是在順序表(即順序存儲(chǔ)的線性表)的表尾進(jìn)行的,其時(shí)間復(fù)雜度為0(1)O
設(shè)一個(gè)棧S為(a,b,c,d,e),對(duì)應(yīng)的順序存儲(chǔ)結(jié)構(gòu)如圖4T(a)所示。若向S
中插入一個(gè)元素f,則對(duì)應(yīng)如圖4T(b)所示。若接著執(zhí)行兩次出棧操作后,則
棧S對(duì)應(yīng)如圖4T(c)所示。若依次使棧S中的所有元素出棧,則s變?yōu)榭?,?/p>
圖4T(d)所示。在圖4T中棧是垂直畫出的,并且使下標(biāo)編號(hào)向上遞增,這樣
可以形象地表示出棧頂在上,棧底在下。
圖4-1棧的順序存儲(chǔ)結(jié)構(gòu)及操作過(guò)程
在一個(gè)順序棧中,若top已經(jīng)指向了StackMaxSizeT的位置,則表示棧
滿,若top的值已經(jīng)等于T,則表示???。向一個(gè)滿棧插入元素和從一個(gè)空棧
刪除元素都是不答應(yīng)的,應(yīng)該停止程序運(yùn)行或進(jìn)行非凡處理。
(2)棧的鏈接存儲(chǔ)結(jié)構(gòu)
棧的鏈接存儲(chǔ)結(jié)構(gòu)與線性表的鏈接存儲(chǔ)結(jié)構(gòu)相同,是通過(guò)由結(jié)點(diǎn)構(gòu)成的單
鏈表實(shí)現(xiàn)的,此時(shí)表頭指針被稱為棧頂指針,由棧頂指針指向的表頭結(jié)點(diǎn)被稱
為棧頂結(jié)點(diǎn),整個(gè)單鏈表被稱為鏈棧,即鏈接存儲(chǔ)的棧。當(dāng)向一個(gè)鏈棧插入元
素時(shí),是把該元素插入到棧頂,即使該元素結(jié)點(diǎn)的指針域指向原來(lái)的棧頂結(jié)
點(diǎn),而棧頂指針則修改為指向該元素結(jié)點(diǎn),使該結(jié)點(diǎn)成為新的棧頂結(jié)點(diǎn)。當(dāng)從
一個(gè)鏈棧中刪除元素時(shí),是把棧頂元素結(jié)點(diǎn)刪除掉,即取出棧頂元素后,使棧
頂指針指向原棧頂結(jié)點(diǎn)的后繼結(jié)點(diǎn)。由此可知,對(duì)鏈棧的插入和刪除操作是在
單鏈表的表頭進(jìn)行的,其時(shí)間復(fù)雜度為0(1)。
設(shè)一個(gè)棧為(a,b,c),當(dāng)采用鏈接存儲(chǔ)時(shí),對(duì)應(yīng)的存儲(chǔ)結(jié)構(gòu)示意圖如圖4-
2(a)所示,其中HS表示棧頂指針,其值為存儲(chǔ)元素c結(jié)點(diǎn)的地址。當(dāng)向這個(gè)棧
插入一個(gè)元素d后,對(duì)應(yīng)如圖4-2(b)所示。當(dāng)從這個(gè)棧依次刪除兩個(gè)元素后,
對(duì)應(yīng)如圖4-2(c)所示。當(dāng)鏈棧中的所有元素全部出棧后,棧頂指針HS的值為
空,即常量NULL所表示的數(shù)值0。
圖4-2棧的鏈接存儲(chǔ)結(jié)構(gòu)及操作過(guò)程
3.棧的抽象數(shù)據(jù)類型
棧的抽象數(shù)據(jù)類型中的數(shù)據(jù)部分為具有ElemType元素類型的一個(gè)棧,它可
以采用任一種存儲(chǔ)結(jié)構(gòu)實(shí)現(xiàn);操作部分包括元素進(jìn)棧、出棧、讀取棧頂元素、
檢查棧是否為空等。下面給出棧的抽象數(shù)據(jù)類型的具體定義。
ADTSTACKisData:
采用順序或鏈接方式存儲(chǔ)的棧,假定其存儲(chǔ)類型用StackType
標(biāo)識(shí)符表示。
Operation:
voidInitStack(StackType&S);
〃初始化棧S,即把它置為空
voidClearStack(StackType&S);
〃清除棧S中的所有元素,使之成為一個(gè)空棧
intStackEmpty(StackType&S);
〃判定S是否為空,若是則返回1,否則返回0ElemType
Peek(StackType&S)
//返回S的棧頂元素,但不移動(dòng)棧頂指針
voidPush(StackType&S,constElemType&item)
〃元素item進(jìn)棧,即插入到棧頂
ElemTypePop(StackType&S)
〃刪除棧頂元素并返回之
intStackFull(Stack&S)
〃若棧已滿則返回1,否則返回0,此函數(shù)為順
//序存儲(chǔ)的棧所特有
endSTACK
對(duì)于判定棧是否為空和返回棧頂元素的兩種操作,由于它們不改變棧的狀
態(tài),所以可在參數(shù)類型說(shuō)明前使用常量定義符const。
假定棧a的元素類型為int,下面給出調(diào)用上述棧操作的一些例子。
(1)InitStack(a);〃把棧a置空
(2)Push(a,35);〃元素35進(jìn)棧
(3)intx=48;Push(a,x);//48進(jìn)棧
(4)Push(a,x/2);//x除以2的值24進(jìn)棧
(5)x=Pop(a);〃棧頂元素24退棧并賦給x
(6)x=Peek(a);//讀取棧頂元素48并賦給x
(7)Pop(a);〃棧頂元素48退棧
(8)StackEmpty(a);〃因棧非空,應(yīng)返回0
(9)coutPop(a)endl;〃棧頂元素35退棧并輸出
(10)x=StackEmpty(a);〃因棧為空,應(yīng)返回1,然后賦給x4.棧運(yùn)算的實(shí)
現(xiàn)
棧運(yùn)算(操作)的具體實(shí)現(xiàn)取決于棧的存儲(chǔ)結(jié)構(gòu),存儲(chǔ)結(jié)構(gòu)不同,其算法描
述也不同。下面分別給出棧的運(yùn)算在順序存儲(chǔ)結(jié)構(gòu)和鏈接存儲(chǔ)結(jié)構(gòu)上實(shí)現(xiàn)的具
體算法。
(a)棧的操作在順序存儲(chǔ)結(jié)構(gòu)上的實(shí)現(xiàn)
假定采用順序存儲(chǔ)結(jié)構(gòu)定義的棧用標(biāo)識(shí)符S表示,其類型為已經(jīng)給出過(guò)的
Stack記錄類型。
(1)初始化棧
voidInitStack(Stack&S)
〃初始化棧S,即把它置為空
S.top=-l;
)
⑵把一個(gè)棧清除為空
在順序存儲(chǔ)方式下,同初始化棧的算法相同。
voidClearStack(Stack&S)
〃清除棧S中的所有元素,使之成為一個(gè)空棧
{
S.top=~l;
)
(3)檢查一個(gè)棧是否為空
intStackEmpty(Stack&S)
〃判定S是否為空,若是則返回1,否則返回0
{
returnS.top==-l;
)
(5)讀取棧頂元素
ElemTypePeek(StackType&S)
〃返回S的棧頂元素,但不移動(dòng)棧頂指針
{
〃若棧為空則終止程序運(yùn)行
if(S.top==~l){
cerr"Stackisempty!”endl;
exit(1);
〃返回棧頂元素的值
returnS.stack[S.top];
)
(5)向棧中插入元素
voidPush(Stack&S,constElemType&item)
〃元素item進(jìn)棧,即插入到棧頂
{
〃若棧己滿則終止程序運(yùn)行
if(S.top==StackMaxSize-1){
cerr'Stackoverflow!”endl;
exit(1);
)
〃將棧頂指針后移一個(gè)位置
S.top++;
〃將item的值賦給新的棧頂位置
S.stack[S.top]=item;
)
(6)從棧中刪除元素
ElemTypePop(StackType&S)
〃刪除棧頂元素并返回之
〃若棧為空則終止程序運(yùn)行
if(S.top==~l){
cerr"Stackisempty!”endl;
exit(1);
〃暫存棧頂元素以便返回
ElemTypetemp=S.stack[S.top];
〃棧頂指針前移一個(gè)位置
S.top一;
〃返回原棧頂元素的值
returntemp;
從出棧算法可以看出,原棧頂元素的值沒(méi)有被改變,所以可以不使用臨時(shí)
變量保存它,返回語(yǔ)句中返回S.stack[S.top+1]的值即可。
(7)檢查棧是否已滿
intStackFull(Stack&S)
〃若棧已滿則返回1,否則返回0,此函數(shù)為順序棧所特有
returnS.top==StackMaxSize-l;
(b)棧的操作在鏈接存儲(chǔ)結(jié)構(gòu)上的實(shí)現(xiàn)
假定鏈棧中的結(jié)點(diǎn)仍采用在第二章中已經(jīng)定義的LNode結(jié)點(diǎn)類型,并假定
棧頂指針用HS表示,下面給出對(duì)由HS所指向的鏈棧進(jìn)行每一種棧操作的算
法。
(1)初始化鏈棧
voidInitStack(LNode*&HS)
HS=NULL;〃將鏈棧置空。
⑵清除鏈棧為空
voidClearStack(LNode*&HS)
{
LNode*cp,*np;
〃用cp作為指向待刪除的結(jié)點(diǎn),np指向cp的后繼結(jié)點(diǎn)。
cp=HS;〃給cp指針賦初值,使之指向棧頂結(jié)點(diǎn)。
while(cp!=NULL)
{〃從棧頂?shù)綏5滓来蝿h除每個(gè)結(jié)點(diǎn)
np=cp-next;
deletecp;
cp=np;
)
HS=NULL;〃置鏈棧為空
)
⑶檢查鏈棧是否為空
intStackEmpty(LNode*HS)
//HS為值參或引用形參均可
(
returnHS==NULL;
}
(4)讀取棧頂元素
ElemTypePeek(LNode*HS)//HS為值參或引用形參均可
{
if(HS==NULL){
cerr"Linkedstackisempty!”endl;
exit(1);
returnHS-data;
⑸向鏈棧中插入一個(gè)元素
voidPush(LNode*&HS,constElemType&item)
{
〃為插入元素獲取動(dòng)態(tài)結(jié)點(diǎn)
LNode*newptr=newLNode;
if(newptr==NULL){
cerr^Memoryallocationfailare!〃endl;
exit(1);
)
〃給新分配的結(jié)點(diǎn)賦值
newptr-data=item;
〃向棧頂插入新結(jié)點(diǎn)
newptr-next=HS;
HS=newptr;
)
(6)從鏈棧中刪除一個(gè)元素
ElemTypePop(LNode*&HS)
(
if(HS==NULL){
cerr"Linkedstackisempty!”endl;
exit(1);
)
LNode*p=HS;〃暫存棧頂結(jié)點(diǎn)
HS=HS-next;〃使棧頂指針指向其后繼結(jié)點(diǎn)
ElemTypetemp=p~data;〃暫存原棧頂元素
deletep;〃回收原棧頂結(jié)點(diǎn)
returntemp;〃返回原棧頂元素
)
5.棧的簡(jiǎn)單應(yīng)用舉例
例L從鍵盤上輸入一批整數(shù),然后按照相反的次序打印出來(lái)。
根據(jù)題意可知,后輸入的整數(shù)將先被打印出來(lái),這正好符合棧的后進(jìn)先出
的特點(diǎn)。所以此題很輕易用棧來(lái)解決。參考程序如下:
Sincludeiostream,h
Sincludestdlib.hconstintStackMaxSize=30;
typedefintElemType;〃定義元素類型為整型
structStack{
ElemTypestack[StackMaxSize];
inttop;
);
Sinclude^stack.h〃
〃假定對(duì)順序棧操作的算法已經(jīng)存于〃stack,h〃頭文件中
voidmain()
Stacka;
InitStack(a);
intx;
cinx;
while(x!=-l){
〃假定用T作為終止鍵盤輸入的標(biāo)志,輸入的整數(shù)個(gè)數(shù)
〃不能超過(guò)StackMaxSize所規(guī)定的值
Push(a,x);
cinx;
)
while(!StackEmpty(a))〃棧不為空時(shí)依次退棧打印出來(lái)
coutPop(a)"";
coutendl;
)
假定從鍵盤上輸入為:
786345829134-1
則輸出為:
349182456378
例2.堆棧在計(jì)算機(jī)語(yǔ)言的編譯過(guò)程中用來(lái)進(jìn)行語(yǔ)法檢查,試編寫一個(gè)算
法,用來(lái)檢查一個(gè)C++語(yǔ)言程序中的花括號(hào)、方括號(hào)和圓括號(hào)是否配對(duì),若能
夠全部配對(duì)則返回1,否則返回0。
在這個(gè)算法中,需要掃描待檢查程序中的每一個(gè)字符,當(dāng)掃描到每個(gè)花、
中、圓左括號(hào)時(shí),令其進(jìn)棧,當(dāng)掃描到每個(gè)花、中、圓右括號(hào)時(shí),則檢查棧頂
是否為相應(yīng)的左括號(hào),若是則作退棧處理,若不是則表明出現(xiàn)了語(yǔ)法錯(cuò)誤,應(yīng)
返回0。當(dāng)掃描到程序文件結(jié)尾后,若棧為空則表明沒(méi)有發(fā)現(xiàn)括號(hào)配對(duì)錯(cuò)誤,
應(yīng)返回1,否則表明棧中還有未配對(duì)的括號(hào),應(yīng)返回0。另外,對(duì)于一對(duì)單引號(hào)
或雙引號(hào)內(nèi)的字符不進(jìn)行括號(hào)配對(duì)檢查。
根據(jù)分析,編寫出算法如下:
intBracketsCheck(char*fname)
〃對(duì)由fname所指字符串為文件名的文件進(jìn)行括號(hào)配對(duì)檢查
(
ifstreamifstr(fname,ios:in|ios:nocreate);
〃用文件輸入流對(duì)象ifstr打開以fname所指字符串為文件名的文件
if(!ifstr){
cerrFile\fname\notfound!endl;
exit(1);
)
Stacka;〃定義一個(gè)順序棧
InitStack(a);〃棧a初始化
charch;
while(ifstrch)〃順序掃描文件中的每一個(gè)字符
{
if(ch==39){〃單引號(hào)內(nèi)的字符不參與配對(duì)比較
while(ifstrch)
if(ch==39)//39為單引號(hào)的ASCH值
break;
if(!ifstr)
return0;
)
elseif(ch==34){〃雙引號(hào)內(nèi)的字符不參與配對(duì)比較
while(ifstrch)
if(ch==34)//34為雙引號(hào)的ASCH值
break;
if(!ifstr)
return0;
)
switch(ch)
case
case
case,(':
Push(a,ch);〃出現(xiàn)以上三種左括號(hào)則進(jìn)棧
break;
case,}‘:
if(Peek(a)==,{')
Pop(a);〃棧頂?shù)淖蠡ɡㄌ?hào)出棧
elsereturn0;
break;
case,]':
if(Peek(a)==,V)
Pop(a);〃棧頂?shù)淖笾欣ㄌ?hào)出棧
elsereturn0;
break;
case,)’:
if(Peek(a)二二'(')
Pop(a);〃棧頂?shù)淖髨A括號(hào)出棧
elsereturn0;
)
)
if(StackEmpty(a))
return1;
elsereturn0;
例3.把十進(jìn)制整數(shù)轉(zhuǎn)換為二至九之間的任一進(jìn)制數(shù)輸出。
由計(jì)算機(jī)基礎(chǔ)知識(shí)可知,把一個(gè)十進(jìn)制整數(shù)X轉(zhuǎn)換為任一種r進(jìn)制數(shù)得到
的是一個(gè)r進(jìn)制的整數(shù),假定為y,轉(zhuǎn)換方法是逐次除基數(shù)r取余法。具體敘
述為:首先用十進(jìn)制整數(shù)x除以基數(shù)r,得到的整余數(shù)是r進(jìn)制數(shù)y的最低位
yO,接著以x除以r的整數(shù)商作為被除數(shù),用它除以r得到的整余數(shù)是y的次
最低位yl,依次類推,直到商為。時(shí)得到的整余數(shù)是y的最高位ym,假定y共
有m+1位。這樣得到的y與x等值,y的按權(quán)展開式為:
y=yO+yl.r+y2.r2+.+ym.rm
例如,若十進(jìn)制整數(shù)為3425,把它轉(zhuǎn)換為八進(jìn)制數(shù)的過(guò)程如圖4-3所示。
圖4-3十進(jìn)制整數(shù)3425轉(zhuǎn)換為八進(jìn)制數(shù)的過(guò)程
最后得到的八進(jìn)制數(shù)為(6541)8,對(duì)應(yīng)的十進(jìn)制數(shù)為6X83+5X82+4X
8+1=3425,即為被轉(zhuǎn)換的十進(jìn)制數(shù),證實(shí)轉(zhuǎn)換過(guò)程是正確的。
從十進(jìn)制整數(shù)轉(zhuǎn)換為r進(jìn)制數(shù)的過(guò)程中,由低到高依次得到r進(jìn)制數(shù)中的
每一位數(shù)字,而輸出時(shí)又需要由高到低依次輸出每一位。所以此問(wèn)題適合利用
棧來(lái)解決,具體算法描述為:
voidTransform(longnum,intr)
〃把一個(gè)長(zhǎng)整型數(shù)num轉(zhuǎn)換為一個(gè)r進(jìn)制數(shù)輸出
(
Stacka;〃利用棧a存儲(chǔ)轉(zhuǎn)換后得到的每一位數(shù)字
InitStack(a);〃初始化棧
while(num!=0)
{〃由低到高求出r進(jìn)制數(shù)的每一位并入棧
intk=num%r;
Push(a,k);
num/=r;
while(!StackEmpty(a))〃由高到低輸出r進(jìn)制數(shù)的每一位
coutPop(a);
coutendl;
假定用下面的主程序調(diào)用Transform過(guò)程。
voidmain()
(
cout”3425的八進(jìn)制數(shù)為:”;
Transform(3425,8);
cout”3425的六進(jìn)制數(shù)為:”;
Transform(3425,6);
cout”3425的四進(jìn)制數(shù)為:”;
Transform(3425,4);
cout”3425的二進(jìn)制數(shù)為:”;
Transform(3425,2);
)
則得到的運(yùn)行結(jié)果如下:
3425的八進(jìn)制數(shù)為:65413425的六進(jìn)制數(shù)為:235053425的四進(jìn)制數(shù)
為:3112013425的二進(jìn)制數(shù)為:110101100001
二、算術(shù)表達(dá)式的計(jì)算
在計(jì)算機(jī)中進(jìn)行算術(shù)表達(dá)式的計(jì)算是通過(guò)棧來(lái)實(shí)現(xiàn)的。這一節(jié)首先討論算
術(shù)表達(dá)式的兩種表示方法,即中綴表示法和后綴表示法,接著討論后綴表達(dá)式
求值的算法,最后討論中綴表達(dá)式轉(zhuǎn)換為后綴表達(dá)式的算法。
1.算術(shù)表達(dá)式的兩種表示
通常書寫的算術(shù)表達(dá)式是由操作數(shù)(又叫運(yùn)算對(duì)象或運(yùn)算量)和運(yùn)算符以及
改變運(yùn)算次序的圓括號(hào)連接而成的式子。操作數(shù)可以是常量、變量和函數(shù),同
時(shí)還可以是表達(dá)式。運(yùn)算符包括單目運(yùn)算符和雙目運(yùn)算符兩類,單目運(yùn)算符只
要求一個(gè)操作數(shù),并被放在該操作數(shù)的前面,雙目運(yùn)算符要求有兩個(gè)操作數(shù),
并被放在這兩個(gè)操作數(shù)的中間。單目運(yùn)算符為取正'+'和取負(fù)'」,雙目運(yùn)算符
有加減乘'*'和除'/'等。為了簡(jiǎn)便起見,在我們的討論中只考慮雙目
運(yùn)算符。
如對(duì)于一個(gè)算術(shù)表達(dá)式2+5*6,乘法運(yùn)算符'*'的兩個(gè)操作數(shù)是它兩邊的5
和6;對(duì)于加法運(yùn)算符'+'的兩個(gè)操作數(shù),一個(gè)是它前面的2,另一個(gè)是它后面
的5*6的結(jié)果即30o我們把雙目運(yùn)算符出現(xiàn)在兩個(gè)操作數(shù)中間的這種習(xí)慣表示
叫做算術(shù)表達(dá)式的中綴表示,這種算術(shù)表達(dá)式被稱為中綴算術(shù)表達(dá)式或中綴表
達(dá)式。
中綴表達(dá)式的計(jì)算比較復(fù)雜,它必須遵守以下三條規(guī)則:
(1)先計(jì)算括號(hào)內(nèi),后計(jì)算括號(hào)外;
(2)在無(wú)括號(hào)或同層括號(hào)內(nèi),先進(jìn)行乘除運(yùn)算,后進(jìn)行加減運(yùn)算,即乘除運(yùn)
算的優(yōu)先級(jí)高于加減運(yùn)算的優(yōu)先級(jí);
(3)同一優(yōu)先級(jí)運(yùn)算,從左向右依次進(jìn)行。
從這三條規(guī)則可以看出,在中綴表達(dá)式的計(jì)算過(guò)程中,既要考慮括號(hào)的作
用,又要考慮運(yùn)算符的優(yōu)先級(jí),還要考慮運(yùn)算符出現(xiàn)的先后次序。因此,各運(yùn)
算符實(shí)際的運(yùn)算次序往往同它們?cè)诒磉_(dá)式中出現(xiàn)的先后次序是不一致的,是不
可猜測(cè)的。當(dāng)然憑直觀判別一個(gè)中綴表達(dá)式中哪個(gè)運(yùn)算符最先算,哪個(gè)次
之,…,哪個(gè)最后算并不困難,但通過(guò)計(jì)算機(jī)處理就比較困難了,因?yàn)橛?jì)算機(jī)
只能一個(gè)字符一個(gè)字符地掃描,要想得到哪一個(gè)運(yùn)算符先算,就必須對(duì)整個(gè)中
綴表達(dá)式掃描一遍,一個(gè)中綴表達(dá)式中有多少個(gè)運(yùn)算符,原則上就得掃描多少
遍才能計(jì)算完畢,這樣就太浪費(fèi)時(shí)間了,顯然是不可取的。
那么,能否把中綴算術(shù)表達(dá)式轉(zhuǎn)換成另一種形式的算術(shù)表達(dá)式,使計(jì)算簡(jiǎn)
單化呢?回答是肯定的。波蘭科學(xué)家盧卡謝維奇(Lukasiewicz)很早就提出了算
術(shù)表達(dá)式的另一種表示,即后綴表示,又稱逆波蘭式,其定義是把運(yùn)算符放在
兩個(gè)運(yùn)算對(duì)象的后面。采用后綴表示的算術(shù)表達(dá)式被稱為后綴算術(shù)表達(dá)式或后
綴表達(dá)式。在后綴表達(dá)式中,不存在括號(hào),也不存在優(yōu)先級(jí)的差別,計(jì)算過(guò)程
完全按照運(yùn)算符出現(xiàn)的先后次序進(jìn)行,整個(gè)計(jì)算過(guò)程僅需一遍掃描便可完成,
顯然比中綴表達(dá)式的計(jì)算要簡(jiǎn)單得多。例如,對(duì)于后綴表達(dá)式12!4!-!5!
/,其中‘!'字符表示成分之間的空格,因減法運(yùn)算符在前,除法運(yùn)算符在后,
所以應(yīng)先做減法,后做除法;減法的兩個(gè)操作數(shù)是它前面的12和4,其中第一
個(gè)數(shù)12是被減數(shù),第二個(gè)數(shù)4是減數(shù);除法的兩個(gè)操作數(shù)是它前面的12減4
的差(即8)和5,其中8是被除數(shù),5是除數(shù)。
中綴算術(shù)表達(dá)式轉(zhuǎn)換成對(duì)應(yīng)的后綴算術(shù)表達(dá)式的規(guī)則是:把每個(gè)運(yùn)算符都
移到它的兩個(gè)運(yùn)算對(duì)象的后面,然后刪除掉所有的括號(hào)即可。
例如,對(duì)于下列各中綴表達(dá)式:
(1)3/5+6
(2)16-9*(4+3)
(3)2*(x+y)/(l-x)
(4)(25+x)*(a*(a+b)+b)
對(duì)應(yīng)的后綴表達(dá)式分別為:
(1)3!5!/!6!+
(2)16!9!4!3!+!*!-
(3)2!x!y!+!*!1!x!-!/
(4)25!x!+!a!a!b!+!*!b!+!*
2.后綴表達(dá)式求值的算法
后綴表達(dá)式的求值比較簡(jiǎn)單,掃描一遍即可完成。它需要使用一個(gè)棧,假
定用S表示,其元素類型應(yīng)為操作數(shù)的類型,假定為浮點(diǎn)型float,用此棧存
儲(chǔ)后綴表達(dá)式中的操作數(shù)、計(jì)算過(guò)程中的中間結(jié)果以及最后結(jié)果。假定一個(gè)后
綴算術(shù)表達(dá)式以字符作為結(jié)束符,并且以一個(gè)字符串的方式提供。后綴表達(dá)
式求值算法的基本思路是:把包含后綴算術(shù)表達(dá)式的字符串定義為一個(gè)輸入字
符串流對(duì)象,每次從中讀入一個(gè)字符(空格作為數(shù)據(jù)之間的分隔符,不會(huì)被作為
字符讀入)時(shí),若它是運(yùn)算符,則表明它的兩個(gè)操作數(shù)已經(jīng)在棧S中,其中棧頂
元素為運(yùn)算符的后一個(gè)操作數(shù),棧頂元素的下一個(gè)元素為運(yùn)算符的前一個(gè)操作
數(shù),把它們彈出后進(jìn)行相應(yīng)運(yùn)算即可,然后把運(yùn)算結(jié)果再壓入棧S中;否則,
讀入的字符必為操作數(shù)的最高位數(shù)字,應(yīng)把它重新送回輸入流中,然后把下一
個(gè)數(shù)據(jù)作為浮點(diǎn)數(shù)輸入,并把它壓入到棧S中。依次掃描每一個(gè)字符(對(duì)于浮點(diǎn)
數(shù)只需掃描它的最高位并一次輸入整個(gè)浮點(diǎn)數(shù))并進(jìn)行上述處理,直到碰到結(jié)束
符'@'為止,表明后綴表達(dá)式計(jì)算完畢,最終結(jié)果保存在棧中,并且棧中僅存這
一個(gè)值,把它彈出返回即可。具體算法描述為:
floatCompute(char*str)
〃計(jì)算由str字符串所表示的后綴表達(dá)式的值,
〃表達(dá)式要以字符結(jié)束。
StackS;〃用S棧存儲(chǔ)操作數(shù)和中間計(jì)算結(jié)果
InitStack(S);//初始化棧
istrstreamins(str);〃把str定義為輸入字符串流對(duì)象inscharch;
〃用于輸入字符
floatx;〃用于輸入浮點(diǎn)數(shù)
insch;〃從ins流對(duì)象(即str字符串)中順序讀入一個(gè)字符
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- LY/T 3405-2024竹材弧形原態(tài)重組材
- 人教版數(shù)學(xué)七年級(jí)下冊(cè)第7課時(shí)《平行線的性質(zhì)(一)》聽評(píng)課記錄
- 2025年造紙色漿合作協(xié)議書
- 湘教版數(shù)學(xué)七年級(jí)上冊(cè)《3.4一元一次方程模型的應(yīng)用(1)》聽評(píng)課記錄
- 蘇人版道德與法治九年級(jí)上冊(cè)7.2《違法要受法律處罰》聽課評(píng)課記錄
- 生態(tài)保護(hù)資源共享合同(2篇)
- 環(huán)境監(jiān)測(cè)設(shè)備合作開發(fā)合同(2篇)
- 六年級(jí)上冊(cè)聽評(píng)課記錄
- (人教版)七年級(jí)下冊(cè)數(shù)學(xué)配套聽評(píng)課記錄:5.1.3 《同位角、內(nèi)錯(cuò)角、同旁內(nèi)角》
- 四年級(jí)科學(xué)聽評(píng)課記錄
- 小學(xué)數(shù)學(xué)6年級(jí)應(yīng)用題100道附答案(完整版)
- 2023年農(nóng)副食品加工項(xiàng)目招商引資方案
- 2024-2029年管道直飲水行業(yè)市場(chǎng)發(fā)展分析及前景趨勢(shì)與投資研究報(bào)告
- 2024年江蘇農(nóng)牧科技職業(yè)學(xué)院?jiǎn)握新殬I(yè)適應(yīng)性測(cè)試題庫(kù)含答案
- 《民航客艙設(shè)備操作與管理》課件-項(xiàng)目二 客艙服務(wù)設(shè)備
- JT-T 1495-2024 公路水運(yùn)危險(xiǎn)性較大工程專項(xiàng)施工方案編制審查規(guī)程
- 麗聲北極星分級(jí)繪本五年級(jí)下(江蘇版)The Moon Cakes 課件
- JT-T-390-1999突起路標(biāo)行業(yè)標(biāo)準(zhǔn)
- 《歌劇魅影》音樂(lè)賞析
- 衛(wèi)星應(yīng)用簡(jiǎn)介演示
- 人教版二年級(jí)上冊(cè)加減混合計(jì)算300題及答案
評(píng)論
0/150
提交評(píng)論