版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
1、書名:數(shù)據(jù)結(jié)構(gòu)ISBN: 978-7-111-49031-9出版社:機(jī)械工業(yè)出版社本書配有電子課件1第三章棧和隊列本章要點(diǎn)棧和隊列的定義、特點(diǎn)棧和隊列基本操作算法的實(shí)現(xiàn)棧和隊列的應(yīng)用33.1 棧3.1.1 棧的定義及基本運(yùn)算 棧是限制在表的一端進(jìn)行插入和刪除操作的線性表。允許插入、刪除的這一端稱為棧頂,另一個固定端稱為棧底。當(dāng)表中沒有元素時稱為空棧。常做的基本運(yùn)算有:(1)棧初始化:Init_SeqStack(s)初始條件:棧s不存在操作結(jié)果:構(gòu)造了一個空棧。(2)判棧空:Empty_SeqStack(s)初始條件:棧s已存在操作結(jié)果:若s為空棧返回為1,否則返回為0。(3)入棧: Push_
2、SeqStack(s,x)初始條件:棧s已存在 操作結(jié)果:在棧s的頂部插入一個新元素x, x成為新的棧頂元素。棧發(fā)生變化。(4)出棧:Pop_SeqStack(s)初始條件:棧s存在且非空操作結(jié)果:棧s的頂部元素從棧中刪除,棧中少了一個元素。(5)取棧頂元素:Get_SeqStack (s)初始條件:棧s存在且非空操作結(jié)果:棧頂元素作為結(jié)果返回,棧不變化。3.1.2 棧的存儲實(shí)現(xiàn)和運(yùn)算實(shí)現(xiàn)1順序棧利用順序存儲方式實(shí)現(xiàn)的棧稱為順序棧。順序棧的類型描述如下:#define MaxSize 50 typedef struct Datatype dataMaxSize; int top; SeqSta
3、ck定義一個指向順序棧的指針:SeqStack *s;通常0下標(biāo)端設(shè)為棧底,這樣空棧時棧頂指針top=-1; 入棧時,棧頂指針加,即s-top+; 出棧時,棧頂指針減,即s-top-。棧操作的示意圖如圖3-2所示。圖(a)是空棧,圖(c)是A、B、C、D、E 5個元素依次入棧之后,圖(d)是在圖(c)之后E、D相繼出棧,此時棧中還有3個元素,通過這個示意圖要深刻理解棧頂指針的作用。(1)初始化空棧初始條件:棧不存在。操作結(jié)果:構(gòu)造一個空棧。 操作步驟:創(chuàng)建一個SeqStack類型的結(jié)構(gòu)體指針s,并返回指針s。算法3.1如下:void Init_SeqStack(SeqStack *s) /算法
4、3.1s-top = 0;(2)判斷空棧初始條件:棧存在。操作結(jié)果:判斷棧是否為空。 操作步驟:判斷棧s是否為空,如果為空返回1,否則返回0。算法3.2如下:int Empty_SeqStack(SeqStack *s) if (s-top= = 0) return 1; else return 0;(3)入棧初始條件:棧s存在。操作結(jié)果:在棧s的頂部插入一個新元素x, x成為新的棧頂元素。int Push_SeqStack (SeqStack *s, Datatype x) if(s-top = MaxSize - 1) printf(溢出n); return 0; else s-datas
5、-top = x; s-top+; return 1; (4)出棧初始條件:棧s存在。操作結(jié)果:棧s的頂部元素從棧中刪除。Datatype Pop_SeqStack(SeqStack *s) Datatype x; if(Empty_SeqStack (s) printf(??課);x = 0; else s-top-; x = (s-data)s-top; return x; /*棧頂元素存入*x,返回*/ (5)取棧頂元素初始條件:棧s存在。操作結(jié)果:從棧s中取出棧頂元素。Datatype Get_SeqStack(SeqStack *s) if ( Empty_SeqStack ( s
6、) ) return 0; /*???/ else return (s-data-s-top ); 2. 鏈棧 用鏈?zhǔn)酱鎯Y(jié)構(gòu)實(shí)現(xiàn)的棧稱為鏈棧。typedef struct node Datatype data;struct node *next;StackNode,* LinkStack;(1)置空棧 初始條件:棧不存在。操作結(jié)果:構(gòu)造一個空棧。LinkStack Init_LinkStack() LinkStack top=(LinkStack)malloc(sizeof(StackNode); top-next=NULL; return top; (2)判斷??粘跏紬l件:棧存在。操作結(jié)果
7、:判斷棧是否為空。int Empty_LinkStack(LinkStack top ) if(top-next=NULL) return 1; else return 0; (3)入棧 初始條件:棧top存在。操作結(jié)果:在棧頂結(jié)點(diǎn)top后插入一新結(jié)點(diǎn),新結(jié)點(diǎn)數(shù)據(jù)元素值為x。Push_LinkStack(LinkStack top, Datatype x) StackNode *s;s= (LinkStack) malloc(sizeof(StackNode);s-data=x; s-next=top-next;top -next =s;(4)出棧初始條件:棧s存在。操作結(jié)果:棧s的頂部元素從
8、棧中刪除。Datatype Pop_LinkStack (LinkStack top, Datatype x) Datatype x; StackNode *p; if (top-next= =NULL) return 0; else p = top-next; x = p-data; top -next = pnext; free (p); return x; 3.2 棧的應(yīng)用舉例【例3-1】編寫一個程序?qū)崿F(xiàn)以下順序棧上的各種基本操作,用一個主程序串成。(1)棧的初始化; (2)棧不滿的情況下元素進(jìn)棧;(3)棧不空的情況下元素出棧;(4)輸出棧中元素;(5)計算棧中元素個數(shù)#include
9、#include#define add 43 #define subs 45 #define mult 42 #define div 47 #define MaxSize 100 typedef struct int dataMaxSize;/*用數(shù)組來表示棧空間,定義長度為MaxSize的棧*/ int top; /*棧頂*/ SeqStack;typedef SeqStack *STK; typedef enumok,error Bool; SeqStack expStackNode; STK expSTK; STK Init_LinkStack(SeqStack *stack_zone)
10、/*執(zhí)行棧初始化,建棧指針*/ STK p; p=stack_zone; p-top=0; return p; Bool Push_LinkStack(int *term,STK pstk)/*將一結(jié)構(gòu)型數(shù)據(jù)送入棧中*/ if(pstk-top=MaxSize) return error; /*棧滿,進(jìn)棧失敗*/ pstk-datapstk-top =*term; (pstk-top)+;/*棧頂指針移動*/ return ok; Bool Empty_LinkStack(STK pstk)/*判斷棧是否為空棧*/ return(pstk-top=0); Bool Pop_LinkStack(
11、int *pdata, STK pstk)/*從棧中取出一結(jié)構(gòu)型數(shù)據(jù)*/ if(Empty_LinkStack(pstk) return error; (pstk-top)-;/*退棧*/ *pdata =pstk-datapstk-top; return ok; int Eval(char tag,int a1,int a2) switch(tag) case add:return(a1+a2); break; case subs:return(a1-a2); break; case mult:return(a1*a2); break; case div:return(a1/a2); bre
12、ak; return ok; void main() char c; int opd1,opd2,temp,c1; expSTK=Init_LinkStack(&expStackNode); printf(n后置表達(dá)式: ); while(c=getchar()!= n ) if(c= ) continue; if(c47)&(c58) /*判斷是否是0-9的字符*/ putchar(c); c1=c-48; /*把輸入的字符型數(shù)字轉(zhuǎn)換成數(shù)字*/ if(Push_LinkStack(&c1,expSTK)=error)/*運(yùn)算分量進(jìn)棧*/ printf(n表達(dá)式太長n); exit(0); e
13、lse if(c=add)|(c=subs)|(c=mult)|(c=div) putchar(c); if(Pop_LinkStack(&opd1,expSTK)=error) /*將運(yùn)算量1出棧*/ printf( n表達(dá)式語法錯! );if(Pop_LinkStack(&opd2,expSTK)=error) /*將運(yùn)算量2出棧*/ printf( n表達(dá)式語法錯! ); temp=Eval(c,opd2,opd1);/*計算得到結(jié)果*/ Push_LinkStack(&temp,expSTK);/*將運(yùn)算結(jié)果進(jìn)棧*/ else printf( n表達(dá)式語法錯! );/*出現(xiàn)非法字符*/
14、 /*while*/ if(Pop_LinkStack(&opd1,expSTK)=error) printf( n表達(dá)式語法錯! ); if(!(Empty_LinkStack(expSTK) printf( n表達(dá)式語法錯! ); printf(=%-3dn,opd1); 【例3-2】數(shù)制轉(zhuǎn)換問題。將十進(jìn)制數(shù)N轉(zhuǎn)換為r進(jìn)制的數(shù),其轉(zhuǎn)換方法利用輾轉(zhuǎn)相除法:以N=3456,r=8為例轉(zhuǎn)換方法如下:(3456)10 =(6563)8#include#includetypedef int Datatype;typedef struct node Datatype data;struct node
15、*next;StackNode, *LinkStack;LinkStack Init_LinkStack()/*初始化棧,算法3.6*/ LinkStack top=(LinkStack)malloc(sizeof(StackNode); top-next=NULL; return top; int Empty_LinkStack(LinkStack top) /*棧判空,算法3.7*/ if(top-next= NULL) return 1; else return 0; void Push_LinkStack(LinkStack top, Datatype x) /*壓棧,算法3.8*/
16、StackNode *s;s=(LinkStack)malloc(sizeof(StackNode);s-data=x; s-next=top-next;top-next=s; int Pop_LinkStack(LinkStack top)/*出棧,算法3.9*/ Datatype x; StackNode *p; if(top-next=NULL) return 0; else p=top-next; x=p-data; top-next=p-next; free (p); return x; void Conversion(int N,int r) /*進(jìn)制的轉(zhuǎn)換*/ LinkStack
17、 s=Init_LinkStack();/*調(diào)用算法3.6,初始化棧*/ printf (轉(zhuǎn)換后的結(jié)果是:,N,r); while(N) Push_LinkStack(s,N%r); /*調(diào)用算法3.8,壓棧*/ N=N/r; while(!Empty_LinkStack(s) /*調(diào)用算法3.7判斷棧是否空*/ printf (%d ,Pop_LinkStack(s); /*調(diào)用算法3.9,出棧*/ printf (n ); void main()int i,r;printf(請輸入待換的數(shù)據(jù));scanf(%d,&i);printf(請輸入轉(zhuǎn)換后的進(jìn)制); scanf(%d,&r); Co
18、nversion(i,r);3.3 隊列3.3.1 隊列的定義及基本運(yùn)算 前面所講的棧是一種“后進(jìn)先出”的數(shù)據(jù)結(jié)構(gòu),而在實(shí)際中還有一種“先進(jìn)先出” (FIFO-First In First Out)的數(shù)據(jù)結(jié)構(gòu):即插入操作在表一端進(jìn)行,而刪除操作在表的另一端進(jìn)行,這種數(shù)據(jù)結(jié)構(gòu)稱為 隊列,把允許插入的一端稱為隊尾(rear) ,把允許刪除的一端稱為隊頭(front)。如圖3-4所示是一個有5 個元素的隊列。入隊的順序依次為:a1、 a2 、a3 、a4 、 a5 出隊的順序依然是:a1、 a2 、a3 、a4 、 a5 隊列是一種運(yùn)算受限制的線性表,在隊列上進(jìn)行的基本操作有:(1)隊列初始化:In
19、it_Queue(q) 初始條件:隊列不存在。 操作結(jié)果:構(gòu)造一個空隊列。(2)入隊操作: In_Queue(q,x), 初始條件:隊列q存在。 操作結(jié)果:對已存在的隊列q,插入一個元素x到隊尾位 置。(3)出隊操作:Out_Queue(q,x) 初始條件:隊q存在且非空 操作結(jié)果:刪除隊首元素,其值用x返回。3.3.2 隊列的存儲實(shí)現(xiàn)及運(yùn)算實(shí)現(xiàn)(1)順序隊列#define MaxSize 50 /*隊列的最大容量*/typedef struct Datatype dataMaxSize; /*隊員的存儲空間*/ int front , rear; /*隊頭隊尾指針*/ SeQueue;定義一
20、個指向隊列的指針變量: SeQueue *q; 隊列的數(shù)據(jù)區(qū)為:q-data0-q-dataMaxSize -1 隊頭指針:q-front 隊尾指針:q-rear 采用順序存儲結(jié)構(gòu)的隊列稱為順序隊。因?yàn)殛犃械年狀^和隊尾都是可以進(jìn)行操作,因此設(shè)有隊頭、隊尾兩個指針。順序隊列的類型定義如下: 設(shè)隊頭指針指向隊頭元素,隊尾指針指向隊尾元素的下一個位置,置空隊則為:q-front=q-rear=0。 在不考慮溢出的情況下,元素入隊,入隊操作后將隊尾指針加1,指向新位置。操作如下:q-dataq-rear=x; /*插入的元素x賦值給隊尾元素*/q-rear+; 在不考慮隊空的情況下,出隊操作將隊頭指針
21、加1,表明隊頭元素出隊。操作如下:x=q-dataq-front;q-front+;隊中元素的個數(shù):m=(q-rear)-(q-front);隊滿時:m= MaxSize; 隊空時:m=0。(a) 空隊列rontrear入隊3個元素a3a2a1frontrear(c) 出隊3個元素frontrear(d) 入隊2個元素a5a4frontrear圖3-5 隊列示意圖 從圖中可以看到,隨著入隊出隊的進(jìn)行,會使整個隊列整體向后移動,這樣就出現(xiàn)了圖3-5(d)中的現(xiàn)象:隊尾指針已經(jīng)移到了最后,再有元素入隊就會出現(xiàn)溢出,而事實(shí)上此時隊中并未真的“滿員”,這種現(xiàn)象為“假溢出”,這是由于“隊尾入隊頭出”這種
22、受限制的操作所造成。解決假溢出的方法之一是將隊列的數(shù)據(jù)區(qū)data0.MaxSize-1看成頭尾相接的循環(huán)結(jié)構(gòu),頭尾指針的關(guān)系不變,將其稱為“循環(huán)隊列”,“循環(huán)隊列”的示意圖如圖3-6所示,頭尾相接的循環(huán)結(jié)構(gòu)。圖3-6循環(huán)隊列示意圖入隊時的隊尾指針加1操作修改為:q-rear=(q-rear+1) % MaxSize;出隊時的隊頭指針加1操作修改為:q-front=(q-front+1) % MaxSize; 設(shè)有循環(huán)隊列,其初始狀態(tài)是front=rear=0,各種操作后隊列的頭、尾指針的狀態(tài)變化情況如下圖3-7所示。 123450(a) 空隊列frontrear123450(b) d, e,
23、b, g入隊frontdebgrear123450(c) d, e出隊bgfrontrear 入隊時尾指針向前追趕頭指針,出隊時頭指針向前追趕尾指針,故隊空和隊滿時頭尾指針均相等。因此,無法通過front=rear來判斷隊列“空”還是“滿”。123450(d)i, j, k入隊bgfrontijkrear123450(e) b, g出隊ijkrearfront123450(f) r, p, s, t入隊ijkfrontrprear圖3-7 循環(huán)隊列操作及指針變化情況 就是說“隊滿”和“隊空”的條件是相同的了,front=rear。這是必須要解決的問題。 方法一:附設(shè)一個存儲隊中元素個數(shù)的變量如
24、num,當(dāng)num=0時隊空,當(dāng)num=MaxSize時為隊滿。 方法二:少用一個元素空間,如3-7圖(f)所示的情況就視為隊滿,也就是說,隊滿時還有一空閑單元,不能再增加元素,此時的狀態(tài):隊尾指針rear+1就會從后面趕上隊頭指針。這種情況下隊滿的條件是:(rear+1) % MaxSize=front,能和隊空front=rear條件區(qū)分開。(1) 置空隊初始條件:隊列不存在。操作結(jié)果:構(gòu)造一個空隊列。void Init_Queue(SeQueue *q) q-front=q-rear=0; (2)入隊初始條件:隊q存在。操作結(jié)果:對已存在的隊列q,插入一個元素x到隊尾。void In_Qu
25、eue(SeQueue *q, Datatype e) if(q-rear+1)%MaxSize=q-front) printf(隊滿); else q-dataq-rear=e; q-rear=(q-rear+1)%MaxSize; (3)出隊 初始條件:隊列q存在。 操作結(jié)果:刪除隊首元素,并返回其值。 int Out_Queue(SeQueue *q, Datatype *e) if(q-front=q-rear) printf(隊空); return 0; /*隊空不能出隊*/ else *e=q-data q-front; /*讀出隊頭元素*/ q-front=(q-front+1)
26、%MaxSize; return 1; /*出隊完成*/ 2. 鏈隊 采用鏈?zhǔn)酱鎯Y(jié)構(gòu)的隊稱為鏈隊。和鏈棧類似,用單鏈表來實(shí)現(xiàn)鏈隊,根據(jù)隊列的FIFO原則,為了操作上的方便,我們分別需要一個頭指針和尾指針,如圖3-8所示。 圖3-8 鏈隊示意圖 圖3-8中頭指針front和尾指針rear是兩個獨(dú)立的指針變量,從結(jié)構(gòu)性上考慮,通常將二者封裝在一個結(jié)構(gòu)中。鏈隊的描述如下: typedef struct node Datatype data; struct node *next; QNode; /*鏈隊結(jié)點(diǎn)的類型*/typedef struct QNnode *front,*rear; LQueue
27、; /*將頭尾指針封裝在一起的鏈隊*/ 定義一個指向鏈隊的指針:LQueue *q;按這種思想建立的帶頭結(jié)點(diǎn)的鏈隊如圖3-9所示。圖3-9 頭尾指針封裝在一起的鏈隊(1)創(chuàng)建一個帶頭結(jié)點(diǎn)的空隊:初始條件:隊列不存在。操作結(jié)果:構(gòu)造一個空隊列。void Init_LQueue(LQueue *q) /*鏈隊列初始化*/q-front = (QNode*)malloc(sizeof(QNode);q-front-next = NULL;q-rear = q-front;(2)入隊初始條件:隊q存在。操作結(jié)果:對已存在的隊列q,插入一個元素x到隊尾。int In_LQueue(LQueue *q,
28、Datatype x)/*元素x 入隊列*/ QNode *s;s=(QNode*)malloc(sizeof(QNode);if(s!=NULL) s-data = x;s-next = NULL;q-rear-next=s;q-rear=s;return 1;else return 0;(3)判隊空初始條件:隊列q存在。操作結(jié)果:若q為空隊則返回為1,否則返回為0。int Empty_LQueue( LQueue *q) if (q-front=q-rear) return 1; else return 0; (4)出隊初始條件:隊列q存在。操作結(jié)果:刪除隊首元素,并返回其值。int De
29、l_LQueue(LQueue *q, Datatype *e) /*刪除隊頭元素并返回*/ QNode *p; if(Empty_LQueue(q) printf(隊列空n);return 0; else p =q-front-next; q-front-next = p-next;if(p-next = NULL) q-rear = q-front; *e = p-data; free(p); return 1;【例3-3】利用隊的順序存儲結(jié)構(gòu),實(shí)現(xiàn)隊列插入,刪除的功能。#include#include #include#define MaxSize 10 /*隊列的最大容量*/typedef struct int aMaxSize; /*隊員的存儲空間*/ int front, rear; /*隊頭隊尾指針*/SeQueue;SeQueue QL;void Init_Queue(SeQueue *q)/*初始化隊列,算法3.10*/ q-front=0;q-rear=0; void Disp_Queue(SeQueue *q)char
溫馨提示
- 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)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 二零二五年度房地產(chǎn)分銷渠道拓展及管理合同3篇
- 轉(zhuǎn)向臂課程設(shè)計卡
- 水文課程設(shè)計模板內(nèi)容
- 2025年百日誓師大會演講稿例文(2篇)
- 2025年社區(qū)文化工作計劃(3篇)
- 學(xué)校長值日制度模版(2篇)
- 學(xué)校傳染病管理制度例文(三篇)
- 2025年度路沿石生產(chǎn)工藝改進(jìn)與創(chuàng)新合作合同3篇
- 二零二五年度水泥預(yù)制品行業(yè)電子商務(wù)平臺建設(shè)合同2篇
- 2024年華東師大版必修1物理下冊階段測試試卷
- 跳倉法施工方案
- SIYB游戲模塊2學(xué)習(xí)供給與需求
- 外研版(2023) 選擇性必修 第二冊 Unit 1 Growing up Developing ideas- The Little Prince教學(xué)設(shè)計(表格式)
- 大班科學(xué)公開課教案及教學(xué)反思《小小測量員》
- TOEFL閱讀100篇附答案
- 輸電線路鐵塔基礎(chǔ)強(qiáng)度加固方案
- 共同富裕思想發(fā)展與精神生活共同富裕
- 鄉(xiāng)村旅游創(chuàng)意景觀的設(shè)計
- 譯林版一年級英語上冊全套ppt
- 物業(yè)公司投標(biāo)文件范本完整版
- 金屬非金屬礦山(地下礦山)考試題庫
評論
0/150
提交評論