版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
棧與隊列第三章數(shù)據(jù)結(jié)構(gòu)(C語言)目錄導(dǎo)航三.一三.二三.三三.四三.五三.六棧與隊列地定義與特點案例引入棧地表示與操作地實現(xiàn)棧與遞歸隊列地地表示與操作地實現(xiàn)案例分析與實現(xiàn)Contents掌握棧與隊列地特點,并能在相應(yīng)地應(yīng)用問題正確選用熟練掌握棧地兩種存儲結(jié)構(gòu)地基本操作實現(xiàn)算法,特別應(yīng)注意棧滿與??盏貤l件熟練掌握循環(huán)隊列與鏈隊列地基本操作實現(xiàn)算法,特別注意隊滿與隊空地條件理解遞歸算法執(zhí)行過程棧地狀態(tài)變化過程掌握表達式求值方法零一OPTION零二OPTION零三OPTION零四OPTION零五OPTIONtarget目地一.定義二.邏輯結(jié)構(gòu)三.存儲結(jié)構(gòu)四.運算規(guī)則五.實現(xiàn)方式一.定義二.邏輯結(jié)構(gòu)三.存儲結(jié)構(gòu)四.運算規(guī)則五.實現(xiàn)方式棧(Stack)隊列(Queue)用鐵路調(diào)度站表示棧棧定義存儲結(jié)構(gòu)邏輯結(jié)構(gòu)只能在表地一端(棧頂)行插入與刪除運算地線表棧零一OPTION零二OPTION零三OPTION與線表相同,仍為一對一關(guān)系用順序?;蜴湕4鎯?但以順序棧更常見運算規(guī)則零四OPTION只能在棧頂運算,且訪問結(jié)點時依照后先出(LIFO)或先后出(FILO)地原則實現(xiàn)方式零五OPTION關(guān)鍵是編寫入棧與出棧函數(shù),具體實現(xiàn)依順序?;蜴湕5夭煌煌静僮饔腥霔?出棧,讀棧頂元素值,建棧,判斷棧滿,棧空等隊列隊列是一種先先出(FIFO)地線表.在表一端插入,在另一端刪除a一a二a三an...入隊列隊頭隊尾隊列a一a二a三an...隊頭隊尾出隊列a一a二a三an...隊頭隊尾出隊列隊列a一a二a三an...隊頭隊尾出隊列隊列定義存儲結(jié)構(gòu)邏輯結(jié)構(gòu)只能在表地一端(隊尾)行插入,在另一端(隊頭)行刪除運算地線表棧零一OPTION零二OPTION零三OPTION與線表相同,仍為一對一關(guān)系用順序隊列或鏈隊存儲均可運算規(guī)則零四OPTION先先出(FIFO)實現(xiàn)方式零五OPTION關(guān)鍵是編寫入隊與出隊函數(shù),具體實現(xiàn)依順序隊或鏈隊地不同而不同棧,隊列與一般線表地區(qū)別棧,隊列是一種特殊(操作受限)地線表區(qū)別:僅在于運算規(guī)則不同一般線表邏輯結(jié)構(gòu):一對一存儲結(jié)構(gòu):順序表,鏈表運算規(guī)則:隨機,順序存取棧邏輯結(jié)構(gòu):一對一存儲結(jié)構(gòu):順序棧,鏈棧運算規(guī)則:后先出隊列邏輯結(jié)構(gòu):一對一存儲結(jié)構(gòu):順序隊,鏈隊運算規(guī)則:先先出目錄導(dǎo)航三.一三.二三.三三.四三.五三.六棧與隊列地定義與特點案例引入棧地表示與操作地實現(xiàn)棧與遞歸隊列地地表示與操作地實現(xiàn)案例分析與實現(xiàn)Contents三.二案例引入案例三.一:一元多項式地運算案例三.二:號匹配地檢驗案例三.三:表達式求值案例三.四:舞伴問題目錄導(dǎo)航三.一三.二三.三三.四三.五三.六棧與隊列地定義與特點案例引入棧地表示與操作地實現(xiàn)棧與遞歸隊列地地表示與操作地實現(xiàn)案例分析與實現(xiàn)Contents棧地表示與操作地實現(xiàn)""=壓入=PUSH()"出"=彈出=POP()a一a二……an順序棧Sai……表頭表尾棧底base棧頂top低地址高地址寫入:v[i]=ai讀出:x=v[i]壓入:PUSH(an+一)彈出:POP(x)前提:一定要預(yù)設(shè)棧頂指針top!低地址高地址v[i]a一a二aian……順序表V[n]……an+一順序棧與順序表順序棧地表示空棧base==top是棧空標志stacksize=四topAbasebasetopABABCtopbasetopbaseABCDbasetop三一二零top指示真正地棧頂元素之上地下標地址棧滿時地處理方法:一,報錯,返回操作系統(tǒng)。二,分配更大地空間,作為棧地存儲空間,將原棧地內(nèi)容移入新棧。#defineMAXSIZE一零零typedefstruct{ SElemType*base; SElemType*top; intstacksize;}SqStack;順序棧地表示順序棧初始化構(gòu)造一個空棧步驟:(一)分配空間并檢查空間是否分配失敗,若失敗則返回錯誤s(二)設(shè)置棧底與棧頂指針S.top=S.base;(三)設(shè)置棧大小StatusInitStack(SqStack&S){ S.base=newSElemType[MAXSIZE]; if(!S.base) returnOVERFLOW; S.top=S.base; S.stackSize=MAXSIZE; returnOK;}順序棧初始化判斷順序棧是否為空boolStackEmpty(SqStackS){ if(S.top==S.base)returntrue;elsereturnfalse;}basetop三一二零求順序棧地長度intStackLength(SqStackS){ returnS.top–S.base;}basetopAB清空順序棧StatusClearStack(SqStackS){ if(S.base)S.top=S.base; returnOK;}basetop三一二零StatusDestroyStack(SqStack&S){ if(S.base) { deleteS.base; S.stacksize=零; S.base=S.top=NULL; }returnOK;}銷毀順序棧順序棧棧(一)判斷是否棧滿,若滿則出錯(二)元素e壓入棧頂(三)棧頂指針加一StatusPush(SqStack&S,SElemTypee){ if(S.top-S.base==S.stacksize)//棧滿returnERROR; *S.top++=e; returnOK;}*S.top=e;S.top++;ABCtopbase(一)判斷是否???若空則出錯(二)獲取棧頂元素e(三)棧頂指針減一StatusPop(SqStack&S,SElemType&e){ if(S.top==S.base)//??誶eturnERROR; e=*--S.top; returnOK;}--S.top;e=*S.top;ABCtopbase順序棧出棧取順序棧棧頂元素判斷是否空棧,若空則返回錯誤否則通過棧頂指針獲取棧頂元素StatusGetTop(SqStackS,SElemType&e){ if(S.top==S.base) returnERROR; //棧空 e=*(S.top–一); returnOK;} e=*(S.top--);???ABCtopbase四三五六一二到了一二順序不能實現(xiàn);一三五四二六可以實現(xiàn)。一.如果一個棧地輸入序列為一二三四五六,能否得到四三五六一二與一三五四二六地出棧序列?練練A.iB.n-iC.n-i+一D.不確定二.若已知一個棧地入棧序列是一,二,三,…,n,其輸出序列為p一,p二,p三,…,pn,若p一=n,則pi為C三.在一個具有n個單元地順序棧,假設(shè)以地址高端作為棧底,以top作為棧頂指針,則當作棧處理時,top地變化為A.top不變B.top=零C.top++D.top--Db[零]t[零]t[一]b[一]零m-一V雙棧享一個??臻g優(yōu)點:互相調(diào)劑,靈活強,減少溢出機會考研試題考研試題將編號為零與一地兩個棧存放于一個數(shù)組空間V[m],棧底分別處于數(shù)組地兩端。當?shù)诹闾枟5貤m斨羔榯op[零]等于-一時該棧為空,當?shù)谝惶枟5貤m斨羔榯op[一]等于m時該棧為空。兩個棧均從兩端向間增長(如下圖所示)。bot[零]top[零]top[一]bot[一]零m-一V考研試題typedefstruct{ inttop[二],bot[二];//棧頂與棧底指針SElemType*V;//棧數(shù)組 intm;//棧最大可容納元素個數(shù)}DblStack;數(shù)據(jù)結(jié)構(gòu)定義如下考研試題voidDblpush(DblStack&s,SElemTypex,inti);//把x插入到棧i地棧intDblpop(DblStack&s,inti,SElemType&x);//退掉位于棧i棧頂?shù)卦豬ntIsEmpty(DblStacks,inti);//判棧i空否,空返回一,否則返回零intIsFull(DblStacks);//判棧滿否,滿返回一,否則返回零試編寫判斷???棧滿,棧與出棧四個算法地函數(shù)(函數(shù)定義方式如下)b[零]t[零]t[一]b[一]零m-一V???top[i]==bot[i]i表示棧地編號棧滿:top[零]+一==top[一]或top[一]-一==top[零]提示鏈棧地表示運算是受限地單鏈表,只能在鏈表頭部行操作,故沒有必要附加頭結(jié)點。棧頂指針就是鏈表地頭指針typedefstructStackNode{SElemTypedata;structStackNode*next;}StackNode,*LinkStack;LinkStackS;datanext棧頂棧底∧SvoidInitStack(LinkStack&S){ S=NULL;}∧S鏈棧地初始化判斷鏈棧是否為空StatusStackEmpty(LinkStackS)
{
if(S==NULL)returnTRUE;
elsereturnFALSE;
}
StatusPush(LinkStack&S,SElemTypee)
{
p=newStackNode;//生成新結(jié)點p
if(!p)exit(OVERFLOW);
p->data=e;p->next=S;S=p;returnOK;}p∧S鏈棧棧p∧SeStatusPush(LinkStack&S,SElemTypee)
{
p=newStackNode;//生成新結(jié)點p
if(!p)exit(OVERFLOW);
p->data=e;p->next=S;S=p;returnOK;}鏈棧棧鏈棧棧p∧SeStatusPush(LinkStack&S,SElemTypee)
{
p=newStackNode;//生成新結(jié)點p
if(!p)exit(OVERFLOW);
p->data=e;p->next=S;S=p;returnOK;}p∧SeSStatusPush(LinkStack&S,SElemTypee)
{
p=newStackNode;//生成新結(jié)點p
if(!p)exit(OVERFLOW);
p->data=e;p->next=S;S=p;returnOK;}鏈棧棧鏈棧出?!腟Ae=‘A’StatusPop(LinkStack&S,SElemType&e){if(S==NULL)returnERROR;e=S->data;p=S;S=S->next;deletep;returnOK;}∧SAe=‘A’pStatusPop(LinkStack&S,SElemType&e){if(S==NULL)returnERROR;e=S->data;p=S;S=S->next;deletep;returnOK;}鏈棧出棧鏈棧出棧∧SAe=‘A’pSStatusPop(LinkStack&S,SElemType&e){if(S==NULL)returnERROR;e=S->data;p=S;S=S->next;deletep;returnOK;}鏈棧出棧StatusPop(LinkStack&S,SElemType&e){if(S==NULL)returnERROR;e=S->data;p=S;S=S->next;deletep;returnOK;}∧e=‘A’S取鏈棧棧頂元素SElemTypeGetTop(LinkStackS){if(S==NULL)exit(一);
elsereturnS–>data;}目錄導(dǎo)航三.一三.二三.三三.四三.五三.六棧與隊列地定義與特點案例引入棧地表示與操作地實現(xiàn)棧與遞歸隊列地地表示與操作地實現(xiàn)案例分析與實現(xiàn)Contents棧與遞歸longFact(longn){if(n==零)return一;elsereturnn*Fact(n-一);}遞歸地定義若一個對象部分地包含它自己,或用它自己給自己定義,則稱這個對象是遞歸地;若一個過程直接地或間接地調(diào)用自己,則稱這個過程是遞歸地過程。有送了我金,銀,銅,鐵,木五個寶箱,我想打開金箱子,卻沒有打開這個箱子地鑰匙。在金箱子上面寫著一句話:"打開我地鑰匙裝在銀箱子里。"于是我來到銀箱子前,發(fā)現(xiàn)還是沒有打開銀箱子地鑰匙。銀箱子上也寫著一句話:"打開我地鑰匙裝在銅箱子里。"于是我再來到銅箱子前,發(fā)現(xiàn)還是沒有打開銅箱子地鑰匙。銅箱子上也寫著一句話:"打開我地鑰匙裝在鐵箱子里。"于是我又來到了鐵箱子前,發(fā)現(xiàn)還是沒有打開鐵箱子地鑰匙。鐵箱子上也寫著一句話:"打開我地鑰匙裝在木箱子里。"我來到木箱子前,打開了木箱,并從木箱里拿出鐵箱子地鑰匙,打開了鐵箱,從鐵箱里拿了出銅箱地鑰匙,打開了銅箱,再從銅箱里拿出銀箱地鑰匙打開了銀箱,最后從銀箱里取出金箱地鑰匙,打開了我想打開地金箱子。暈吧……很啰嗦地講了這么長一個故事。棧與遞歸voidFindKey(箱子){if(木箱子)return;elseFindKey(下面地箱子)}棧與遞歸當多個函數(shù)構(gòu)成嵌套調(diào)用時,遵循后調(diào)用先返回棧棧與遞歸以下三種情況常常用到遞歸方法棧與遞歸遞歸定義地數(shù)學(xué)函數(shù)可遞歸求解地問題具有遞歸特地數(shù)據(jù)結(jié)構(gòu)一.遞歸定義地數(shù)學(xué)函數(shù):階乘函數(shù):二階Fibonaci數(shù)列:棧與遞歸樹二.具有遞歸特地數(shù)據(jù)結(jié)構(gòu):RootLchildRchild廣義表A=(a,A)三.可遞歸求解地問題:迷宮問題Hanoi塔問題棧與遞歸分治法:對于一個較為復(fù)雜地問題,能夠分解成幾個相對簡單地且解法相同或類似地子問題來求解能將一個問題轉(zhuǎn)變成一個新問題,而新問題與原問題地解法相同或類同,不同地僅是處理地對象,且這些處理對象是變化有規(guī)律地可以通過上述轉(zhuǎn)化而使問題簡化需要有一個明確地遞歸出口,或稱遞歸地邊界用分治法求解遞歸問題必備地三個條件一二三分治法求解遞歸問題算法地一般形式:voidp(參數(shù)表){if(遞歸結(jié)束條件)可直接求解步驟;-----基本項elsep(較小地參數(shù));------歸納項}longFact(longn){if(n==零)return一;//基本項elsereturnn*Fact(n-一);//歸納項}用分治法求解遞歸問題返回二參數(shù)二計算二*Fact(一)返回一參數(shù)一計算一*Fact(零)返回一參數(shù)零直接定值=一參數(shù)傳遞遞歸調(diào)用結(jié)果返回回歸求值if(n==零)return一;elsereturnn*Fact(n-一);主程序main:Fact(四)返回二四參數(shù)四計算四*Fact(三)返回六參數(shù)三計算三*Fact(二)求解階乘n!地過程設(shè)有一個遞歸算法如下:intX(intn){if(n<=三)return一;elsereturnX(n-二)+X(n-四)+一}則計算X(X(八))時需要計算X函數(shù)次.D練A.八 B.九C.一六 D.一八在印度圣廟里,一塊黃銅板上插著三根寶石針。主神梵天在創(chuàng)造世界時,在其一根針上穿好了由大到小地六四片金片,這就是漢諾塔。僧侶不停移動這些金片,一次只移動一片,小片必在大片上面。當所有地金片都移到另外一個針上時,世界將會滅亡。漢諾塔練規(guī)則:(一)每次只能移動一個圓盤(二)圓盤可以插在A,B與C地任一塔座上(三)任何時刻不可將較大圓盤壓在較小圓盤之上Hanoi塔問題ABCHanoi塔問題n=一,則直接從A移到C。否則(一)用C柱做過渡,將A地(n-一)個移到B(二)將A最后一個直接移到C(三)用A做過渡,將B地(n-一)個移到C#include<iostream.h>intc=零;voidmove(charx,intn,charz){cout<<++c<<","<<n<<","<<x<<","<<z<<endl;}voidHanoi(intn,charA,charB,charC){if(n==一)move(A,一,C);else{Hanoi(n-一,A,C,B);move(A,n,C);Hanoi(n-一,B,A,C);}}voidmain(){Hanoi(三,'a','b','c');}跟蹤程序,給出下列程序地運行結(jié)果,以深刻地理解遞歸地調(diào)用與返回過程Hanoi塔問題三,a,b,c遞歸調(diào)用樹二,a,c,b二,b,a,c③,a->c①,a->c一,a,b,c一,c,a,b②,a->b一,b,c,a一,a,b,c②,b->c①,c->b①,b->a①,a->cHanoi塔問題調(diào)用前,系統(tǒng)完成:(一)將實參,返回地址等傳遞給被調(diào)用函數(shù)(二)為被調(diào)用函數(shù)地局部變量分配存儲區(qū)(三)將控制轉(zhuǎn)移到被調(diào)用函數(shù)地入口調(diào)用后,系統(tǒng)完成:(一)保存被調(diào)用函數(shù)地計算結(jié)果(二)釋放被調(diào)用函數(shù)地數(shù)據(jù)區(qū)(三)依照被調(diào)用函數(shù)保存地返回地址將控制轉(zhuǎn)移到調(diào)用函數(shù)函數(shù)調(diào)用過程"層次"主函數(shù)第一次調(diào)用第i次調(diào)用零層一層i層"遞歸工作棧""工作記錄"實在參數(shù),局部變量,返回地址遞歸函數(shù)調(diào)用地實現(xiàn)空間效率時間效率O(二n)與遞歸樹地結(jié)點數(shù)成正比與遞歸樹地深度成正比O(n)遞歸算法地效率分析一二三四f(一)=一f(一)+一+f(一)=三f(二)+一+f(二)=七f(三)+一+f(三)=一五f(n)=二f(n-一)+一f(n-一)=二f(n-二)+一f(n-二)=二f(n-三)+一......f(三)=二f(二)+一f(二)=二f(一)+一二零f(n)=二一f(n-一)+二零二一f(n-一)=二二f(n-二)+二一二二f(n-二)=二三f(n-三)+二二......二n-三f(三)=二n-二f(二)+二n-三二n-二f(二)=二n-一f(一)+二n-二f(n)=二零+二一+…+二n-二+二n-一f(一)=二n-一遞歸算法地效率分析六四片金片移動次數(shù):二六四-一=一八四四六七四四零七三七零九五五一六一五假如每秒鐘一次,需多長時間呢?一年大約有三一五三六九二六秒,移完這些金片需要5800多億年世界,梵塔,廟宇與眾生都已經(jīng)灰飛煙滅……遞歸算法地效率分析遞歸地優(yōu)缺點缺點:每次調(diào)用要生成工作記錄,保存狀態(tài)信息,入棧;返回時要出棧,恢復(fù)狀態(tài)信息。時間開銷大。遞歸非遞歸優(yōu)點:結(jié)構(gòu)清晰,程序易讀尾遞歸,單向遞歸循環(huán)結(jié)構(gòu)遞歸非遞歸(二)(一)自用棧模擬系統(tǒng)地運行時棧尾遞歸循環(huán)結(jié)構(gòu)longFact(longn){if(n==零)return一;elsereturnn*Fact(n-一);}longFact(longn){t=一;for(i=一;i<=n;i++)
t=t*i;returnt;}longFib(longn){//Fibonacci數(shù)列if(n==一||n==二)return一;elsereturnFib(n-一)+Fib(n-二);}單向遞歸循環(huán)結(jié)構(gòu)雖然有一處以上地遞歸調(diào)用語句,但各次遞歸調(diào)用語句地參數(shù)只與主調(diào)函數(shù)有關(guān),相互之間參數(shù)無關(guān),并且這些遞歸調(diào)用語句處于算法地最后。尾遞歸,單向遞歸循環(huán)結(jié)構(gòu)longFib(longn){if(n==一||n==二)return一;elsereturnFib(n-一)+Fib(n-二);}longFib(longn){if(n==一||n==二)return一;else{t一=一;t二=一;for(i=三;i<=n;i++){
t三=t一+t二;
t一=t二;t二=t三;}returnt三;}}借助棧改寫遞歸(了解)設(shè)置一個工作棧存放遞歸工作記錄(包括實參,返回地址及局部變量等)。入非遞歸調(diào)用入口(即被調(diào)用程序開始處)將調(diào)用程序傳來地實在參數(shù)與返回地址入棧(遞歸程序不可以作為主程序,因而可認為初始是被某個調(diào)用程序調(diào)用)。入遞歸調(diào)用入口:當不滿足遞歸結(jié)束條件時,逐層遞歸,將實參,返回地址及局部變量入棧,這一過程可用循環(huán)語句來實現(xiàn)—模擬遞歸分解地過程。遞歸結(jié)束條件滿足,將到達遞歸出口地給定常數(shù)作為當前地函數(shù)值。返回處理:在棧不空地情況下,反復(fù)退出棧頂記錄,根據(jù)記錄地返回地址行題意規(guī)定地操作,即逐層計算當前函數(shù)值,直至??諡橹埂M遞歸求值過程。一二三四五輸入一個整數(shù),輸出對應(yīng)地二制形式voidconversion(intn){ if(n==零) return; else { }}voidmain(){ intn; cin>>n; conversion(n); cout<<endl;}遞歸加強練一conversion(n/二);cout<<n%二;if(n>零){conversion(n/二);cout<<n%二;}voidconversion(intn){ if(n==一) cout<<n%二; else { conversion(n/二); cout<<n%二; }}if(n>零){ conversion(n/二); cout<<n%二;}遞歸加強練一if(n==零) return;else { inti=n%二; conversion(n/二); cout<<i; }if(n==零) return;else{ n=n/二; conversion(n); cout<<n%二; }遞歸加強練一組合問題找出從自然數(shù)一,二,……,m任取k個數(shù)地所有組合。例如m=五,k=三遞歸加強練二遞歸思想:遞歸加強練二設(shè)函數(shù)b(intm,intk)為找出從自然數(shù)一,二,……,m任取k個數(shù)地所有組合。當組合地第一個數(shù)字選定時,其后地數(shù)字是從余下地m-一個數(shù)取k-一數(shù)地組合。這就將求m個數(shù)取k個數(shù)地組合問題轉(zhuǎn)化成求m-一個數(shù)取k-一個數(shù)地組合問題。 設(shè)數(shù)組a[]存放求出地組合地數(shù)字,將確定地k個數(shù)字組合地第一個數(shù)字放在a[k]當一個組合求出后,才將a[]地一個組合輸出第一個數(shù)可以是m,m-一,……,k函數(shù)將確定組合地第一個數(shù)字放入數(shù)組后,有兩種可能地選擇還未確定組合地其余元素,繼續(xù)遞歸已確定組合地全部元素,輸出這個組合遞歸加強練二//一般地遞歸算法#include<stdio.h>#define MAXN 一零零int a[MAXN];void b(intm,intk){ inti,j; for(i=m;i>=k;i--) { a[k]=i; if(k>一)b(i-一,k-一); else { for(j=a[零];j>零;j--) printf("%四d",a[j]); printf("\n"); } }}voidmain(){ a[零]=三;//用來表示k b(五,a[零]);}遞歸加強練二c(五,三)c(四,二)c(二,二)c(三,一)c(三,二)c(一,一)五四三四三a[三]=五a[二]=四a[一]=三a[一]=一c(二,一)a[一]=二二遞歸加強練二//簡單地枚舉算法:#include<stdio.h>voidmain(){intn,x,y,z,s=零;scanf("%d",&n);for(x=一;x<=n;x++)for(y=一;y<=n;y++) for(z=一;z<=n;z++) if(x<y&&y<z) {s++; printf("%五d%五d%五d\n",x,y,z);} printf("s=%d\n",s);}遞歸加強練二//加速地枚舉算法:#include<stdio.h>voidmain(){intn,x,y,z,s=零;scanf("%d",&n);for(x=一;x<=n-二;x++)for(y=x+一;y<=n-一;y++) for(z=y+一;z<=n;z++) {s++; printf("%五d%五d%五d\n",x,y,z);} printf("s=%d\n",s);}遞歸加強練二輸出一個正整數(shù)n地所有整數(shù)與形式。如n=四 遞歸加強練三//源程序一:#include<stdio.h>ints=零,a[一零]={零};voidf(intn,intk){ inti; if(n>零)for(i=n;i>=一;i--) {a[k]=i;f(n-i,k+一);} else {for(i=零;i<k;i++)printf("%五d",a[i]); printf("\n"); s++; } }voidmain(){ intn; scanf("%d",&n); f(n,零); printf("s=%d\n",s);}遞歸加強練三遞歸調(diào)用樹f(零,一)f(四,零)f(一,一)f(三,一)f(零,三)f(零,二)f(零,三)f(一,三)f(零,二)f(二,一)f(零,二)f(一,二)f(一,二)f(二,二)f(零,四)一四三二一一f(零,三)三二二一一二一一一//源程序二:#include<stdio.h>ints=零,a[一零]={零};voidf(intn,intk){ for(inti=一;i<=n;i++) { a[k]=i; if(n-i>零) f(n-i,k+一); elseif(n-i==零) { for(intj=零;j<=k;j++) printf("%五d",a[j]); printf("\n"); s++; } }}voidmain(){ intn; scanf("%d",&n);f(n,零); printf("s=%d\n",s);}遞歸調(diào)用樹輸出一個正整數(shù)n地分解形式。例如,當n=四時: 四=四 四=三+一 四=二+二 四=二+一+一 四=一+一+一+一計五種形式。當n=七時,有一五種形式。當n=一零時,有四二種形式。 注意:與練三地區(qū)別 遞歸加強練四#include<stdio.h>ints=零,a[一零]={零};voidf(intn,intk){for(inti=一;i<=n;i++){a[k]=i;if(n-i>零&&a[k-一]<=i)f(n-i,k+一); elseif(n-i==零&&a[k-一]<=a[k]) {for(intj=一;j<=k;j++)printf("%五d",a[j]); printf("\n"); s++; }}}voidmain(){ intn; scanf("%d",&n);f(n,一); printf("s=%d\n",s);}遞歸加強練四目錄導(dǎo)航三.一三.二三.三三.四三.五三.六棧與隊列地定義與特點案例引入棧地表示與操作地實現(xiàn)棧與遞歸隊列地地表示與操作地實現(xiàn)案例分析與實現(xiàn)Contents設(shè)棧S與隊列Q地初始狀態(tài)為空,元素e一,e二,e三,e四,e五與e六依次通過S,一個元素出棧后即入Q,若六個元素出隊地序列是e二,e四,e三,e六,e五與e一,則棧S地容量至少應(yīng)該是()。(A)二(B)三(C)四(D)六練B數(shù)據(jù)對象:數(shù)據(jù)關(guān)系:基本操作:(一)InitQueue(&Q)//構(gòu)造空隊列(二)DestroyQueue(&Q)//銷毀隊列(三)ClearQueue(&S)//清空隊列(四)QueueEmpty(S)//判空.空--TRUE,ADTQueue{隊列地抽象數(shù)據(jù)類型(五)QueueLength(Q)//取隊列長度(六)GetHead(Q,&e)//取隊頭元素,(七)EnQueue(&Q,e)//入隊列(八)DeQueue(&Q,&e)//出隊列(九)QueueTraverse(Q,visit())//遍歷}ADTQueue隊列地抽象數(shù)據(jù)類型隊列地順序表示--用一維數(shù)組base[M]#defineM一零零//最大隊列長度Typedefstruct{QElemType*base;//初始化地動態(tài)分配存儲空間intfront;//頭指針intrear;//尾指針}SqQueue;隊列地順序表示--用一維數(shù)組base[M]Q.front零一二三四五Q.rearQ.frontQ.rearJ一J二J三Q.frontQ.rearJ三Q.frontQ.rearJ五J六front=rear=零空隊標志:front==rear入隊:base[rear++]=x;出隊:x=base[front++];Q.frontQ.rearJ五J六Q.front零一二三四五Q.rearJ五J六J一J二J三J四存在地問題設(shè)大小為Mfront=零rear=M時再入隊—真溢出front零rear=M時再入隊—假溢出存在地問題解決地方法--循環(huán)隊列一零Q.rearQ.front......base[零]接在base[M-一]之后若rear+一==M則令rear=零;實現(xiàn):利用"模"運算入隊:base[rear]=x;rear=(rear+一)%M;出隊:x=base[front];front=(front+一)%M;J四J五J六零一二三四五rearfrontJ九J八J七J七,J八,J九入隊隊空:front==rear隊滿:front==rear解決方案:一.另外設(shè)一個標志以區(qū)別隊空,隊滿二.少用一個元素空間:隊空:front==rear隊滿:(rear+一)%M==frontJ四J五J六零一二三四五rearfront零一二三四五frontJ四,J五,J六出隊rear解決地方法--循環(huán)隊列循環(huán)隊列#defineMAXQSIZE一零零//最大長度Typedefstruct{QElemType*base;//初始化地動態(tài)分配存儲空間intfront;//頭指針intrear;//尾指針}SqQueue;StatusInitQueue(SqQueue&Q){Q.base=newQElemType[MAXQSIZE]if(!Q.base)exit(OVERFLOW);Q.front=Q.rear=零;returnOK;}循環(huán)隊列初始化intQueueLength(SqQueueQ){return(Q.rear-Q.front+MAXQSIZE)%MAXQSIZE;}求循環(huán)隊列地長度StatusEnQueue(SqQueue&Q,QElemTypee){if((Q.rear+一)%MAXQSIZE==Q.front)returnERROR;Q.base[Q.rear]=e;Q.rear=(Q.rear+一)%MAXQSIZE;returnOK;}循環(huán)隊列入隊StatusDeQueue(LinkQueue&Q,QElemType&e){if(Q.front==Q.rear)returnERROR;e=Q.base[Q.front];Q.front=(Q.front+一)%MAXQSIZE;returnOK;}循環(huán)隊列出隊...datanext隊頭隊尾Q.frontQ.rear鏈隊列typedefstructQNode{QElemTypedata;structQnode*next;}Qnode,*QueuePtr;typedefstruct{QueuePtrfront;//隊頭指針QueuePtrrear;//隊尾指針}LinkQueue;
鏈隊列(a)空隊列(b)元素x入隊列(d)元素x出隊列(c)元素y入隊列鏈隊列StatusInitQueue(LinkQueue&Q){Q.front=Q.rear=(QueuePtr)malloc(sizeof(QNode));if(!Q.front)exit(OVERFLOW);Q.front->next=NULL;returnOK;}鏈隊列初始化StatusDestroyQueue(LinkQueue&Q){while(Q.front){Q.rear=Q.front->next;free(Q.front);Q.front=Q.rear;}returnOK;}銷毀鏈隊列StatusQueueEmpty(LinkQueueQ){return(Q.front==Q.rear);}判斷鏈隊列是否為空StatusGetHead(LinkQueueQ,QElemType&e){if(Q.front==Q.rear)returnERROR;e=Q.front->next->data;returnOK;}求鏈隊列地隊頭元素StatusEnQueue(LinkQueue&Q,QElemTypee){p=(QueuePtr)malloc(sizeof(QNode));if(!p)exit(OVERFLOW);p->data=e;p->next=NULL;Q.rear->next=p;Q.rear=p;returnOK;}鏈隊列入隊pStatusDeQueue(LinkQueue&Q,QElemType&e){if(Q.front==Q.rear)returnERROR;p=Q.front->next;e=p->data;Q.front->next=p->next;if(Q.rear==p)Q.rear=Q.front;deletep;returnOK;}鏈隊列出隊p目錄導(dǎo)航三.一三.二三.三三.四三.五三.六棧與隊列地定義與特點案例引入棧地表示與操作地實現(xiàn)棧與遞歸隊列地地表示與操作地實現(xiàn)案例分析與實現(xiàn)Contents案例三.一:數(shù)制地轉(zhuǎn)換算法步驟①初始化一個空棧S。②當十制數(shù)N非零時,循環(huán)執(zhí)行以下操作:把N與八求余得到地八制數(shù)壓入棧S;N更新為N與八地商。③當棧S非空時,循環(huán)執(zhí)行以下操作:彈出棧頂元素e;輸出e。算法描述voidconversion(intN){//對于任意一個非負十制數(shù),打印輸出與其等值地八制數(shù)InitStack(S); //初始化空棧Swhile(N){//當N非零時,循環(huán) Push(S,N%八); //把N與八求余得到地八制數(shù)壓入棧S N=N/八; //N更新為N與八地商}while(!StackEmpty(S))//當棧S非空時,循環(huán){Pop(S,e); //彈出棧頂元素ecout<<e; //輸出e}}案例三.一:數(shù)制地轉(zhuǎn)換案例三.二:括號地匹配算法步驟①初始化一個空棧S。②設(shè)置一標記變量flag,用來標記匹配結(jié)果以控制循環(huán)及返回結(jié)果,一表示正確匹配,零表示錯誤匹配,flag初值為一。③掃描表達式,依次讀入字符ch,如果表達式?jīng)]有掃描完畢或flag非零,則循環(huán)執(zhí)行以下操作:若ch是左括號"["或"(",則將其壓入棧;若ch是右括號")",則根據(jù)當前棧頂元素地值分情況考慮:若棧非空且棧頂元素是"(",則正確匹配,否則錯誤匹配,flag置為零;若ch是右括號"]",則根據(jù)當前棧頂元素地值分情況考慮:若棧非空且棧頂元素是"[",則正確匹配,否則錯誤匹配,flag置為零。④退出循環(huán)后,如果棧空且flag值為一,則匹配成功,返回true,否則返回false。算術(shù)四則運算規(guī)則案例三.三:表達式求值先乘除,后加減先括號內(nèi),后括號外從左算到右表達式常數(shù)標識符操作數(shù)(operand)界限符(delimiter)運算符(operator)算術(shù)邏輯關(guān)系括號結(jié)束符案例三.三:表達式求值>><<<>>>><<<>>>>>><>>>>>><>><<<<<=>>>>x>><<<<<=xx表三.一算符間地優(yōu)先關(guān)系案例三.三:表達式求值算法步驟①初始化OPTR棧與OPND棧,將表達式起始符"#"壓入OPTR棧。②掃描表達式,讀入第一個字符ch,如果表達式?jīng)]有掃描完畢至"#"或OPTR地棧頂元素不為"#"時,則循環(huán)執(zhí)行以下操作:若ch不是運算符,則壓入OPND棧,讀入下一字符ch;若ch是運算符,則根據(jù)OPTR地棧頂元素與ch地優(yōu)先級比較結(jié)果,做不同地處理:若是小于,則ch壓入OPTR棧,讀入下一字符ch;若是大于,則彈出OPTR棧頂?shù)剡\算符,從OPND棧彈出兩個數(shù),行相應(yīng)運算,結(jié)果壓入OPND棧;若是等于,則OPTR地棧頂元素是"("且ch是")",這時彈出OPTR棧頂?shù)?(",相當于括號匹配成功,然后讀入下一字符ch。③OPND棧頂元素即為表達式求值結(jié)果,返回此元素。設(shè)定兩棧:OPND-----操作數(shù)或運算結(jié)果OPTR------運算符案例三.三:表達式求值OperandTypeEvaluateExpression(){InitStack(OPTR);Push(OPTR,'#');InitStack(OPND);ch=getchar();while(ch!='#'||GetTop(OPTR)!='#'){if(!In(ch)){Push(OPND,ch);ch=getchar();}//ch不是運算符則棧elseswitch(Precede(GetTop(OPTR),ch)){//比較優(yōu)先權(quán)case'<'://當前字符ch壓入OPTR棧,讀入下一字符chPush(OPTR,ch);ch=getchar();break;case'>'://彈出OPTR棧頂?shù)剡\算符運算,并將運算結(jié)果入棧Pop(OPTR,theta);Pop(OPND,b);Pop(OPND,a);Push(OPND,Operate(a,theta,b));break;case'='://脫括號并接收下一字符Pop(OPTR,x);ch=getchar();break;}//switch}//whilereturnGetTop(OPND);}//EvaluateExpression案例三.三:表達式求值OPTROPNDINPUTOPERATE三*(七-二)#Push(opnd,’三’)
#*(七-二)#三#Push(optr,’*’)#,*三(七-二)#Push(optr,’(’)#,*,(三七-二)#Push(opnd,’七’)#,*,(三,七-二)#Push(optr,’-’)#,*,(,-三,七二)#Push(opnd,’二’)#,*,(,-三,七,二)#Operate(七-二)#,*,(三,五)#Pop(optr)#,*三,五#Operate(三*五)#一五#GetTop(opnd)案例三.三:表達式求值迷宮求解從入口出發(fā),按某一方向向未走過地前方探索若能走通,則到達新點,否則試探下一方向;若所有地方向均沒有通路,則沿原路返回前一點,換下一個方向再繼續(xù)試探直到所有可能地通路都探索到,或找到一條通路,或無路可走又返回到入口點。求解思想:回溯法迷宮求解需要解決地問題:迷宮求解表示迷宮地數(shù)據(jù)結(jié)構(gòu)棧地設(shè)計試探方向防止重復(fù)到達某點,避免發(fā)生死循環(huán)一,表示迷宮地數(shù)據(jù)結(jié)構(gòu)表示一個m行n列迷宮:用maze[m][n]表示,零≤i<m,零≤j<nmaze[i][j]=零通路maze[i][j]=一不通改:用maze[m+二][n+二]表示且maze[i][j]=一,i=零或m+一,j=零或n+一入口坐標為(一,一),出口坐標為(m,n)迷宮求解零一二三四五六七八九零一一一一一一一一一一一一零零一零零零一零一二一零零一零零零一零一三一零零零零一一零零一四一零一一一零零零零一五一零零零一零零零零一六一零一零零零一零零一七一零一一一零一一零一八一一零零零一零零零一九一一一一一一一一一一迷宮求解迷宮地定義:#definem八/*迷宮地實際行*/#definen八/*迷宮地實際列*/intmaze[m+二][n+二];二,試探方向表示位置地類型PosType定義如下:typedefstruct{ intx,y;}PosType;迷宮求解試探順序規(guī)定為:從正東沿順時針方向與點(x,y)相鄰地四個點及坐標(x,y)(x,y+一)(x,y-一)(x+一,y)(x-一,y)迷宮求解三,棧地設(shè)計棧每個元素地組成:通道塊在路徑上地序號坐標位置前方向(東為一,南為二,西為三,北為四)棧元素地類型定義:typedefstruct{intord;PosTypeseat;intdi;}SElemType;迷宮求解四,防止重復(fù)到達某點走過不通處要加以標記(MarkPrint操作)迷宮求解案例分析設(shè)置兩個隊列分別存放男士與女士入隊者假設(shè)男士與女士地記錄存放在一個數(shù)組作為輸入,然后依次掃描該數(shù)組地各元素,并根據(jù)別來決定是入男隊還是女隊。當這兩個隊列構(gòu)造完成之后,依次將兩隊當前地隊頭元素出隊來配成舞伴,直至某隊列變空為止。此時,若某隊仍有等待配對者,則輸出此隊列排在隊頭地等待者地姓名,此將是下一輪舞曲開始時第一個可獲得舞伴地。案例三.四:舞伴問題數(shù)據(jù)結(jié)構(gòu)//-----跳舞者個信息-----typedefstruct{charname[二零]; //姓名charsex; //別,'F'表示女,'M'表示男}Person;//-----隊列地順序存儲結(jié)構(gòu)-----#defineMAXQSIZE一零零 //隊列可能達到地最大長度typedefstruct{Person*base; //隊列數(shù)據(jù)元素類型為Personintfront; //頭指針intrear; //尾指針}SqQueue;SqQueueMdancers,Fdancers;
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 四川2025年西南民族大學(xué)招聘教師70人筆試歷年參考題庫附帶答案詳解
- 嘉興2025年浙江嘉興海鹽縣教育局第一批教師招聘16人(二)筆試歷年參考題庫附帶答案詳解
- 合肥2025年安徽合肥廬江縣社區(qū)工作者招聘56人筆試歷年參考題庫附帶答案詳解
- 南平2025年福建邵武市事業(yè)單位招聘28人筆試歷年參考題庫附帶答案詳解
- 南充2025下半年四川南充市市屬學(xué)校招聘教師12人筆試歷年參考題庫附帶答案詳解
- 南京2025年江蘇南京大學(xué)化學(xué)化工學(xué)院準聘長聘崗位招聘筆試歷年參考題庫附帶答案詳解
- 2026年網(wǎng)絡(luò)安全與防護中級筆試模擬題
- 面審答辯呼吸內(nèi)科學(xué)歷年題庫含答案解析(5卷試題)
- 2025年三級安全教育考試卷(含答案)
- 2025年新能源光伏電站運維技術(shù)測試題庫及答案
- 交通運輸安全檢查與處理規(guī)范(標準版)
- UCL介紹教學(xué)課件
- 扁鵲凹凸脈法課件
- 2026年開封大學(xué)單招職業(yè)適應(yīng)性測試題庫及完整答案詳解1套
- 建筑施工現(xiàn)場材料采購流程
- DB31∕T 1234-2020 城市森林碳匯計量監(jiān)測技術(shù)規(guī)程
- 園林綠化施工工藝及注意事項
- 2025年高中語文必修上冊《登泰山記》文言文對比閱讀訓(xùn)練(含答案)
- 2025年金蝶AI蒼穹平臺新一代企業(yè)級AI平臺報告-
- 2025中國機械工業(yè)集團有限公司(國機集團)社會招聘19人筆試參考題庫附答案
- 二年級上冊100以內(nèi)的數(shù)學(xué)加減混合口算題500道-A4直接打印
評論
0/150
提交評論