棧有乙個很重要的應用:在程式語言中講了遞迴。那麼什麼是遞迴呢?當你往鏡子前面一站,鏡子裡面就有乙個你的像。但你試過兩面鏡子一起照嗎?如果a、b兩面鏡子互相面對面放著,你往中間一站,嘿,兩面鏡子都有你的千百個「化身」,為什麼會有這麼奇妙的現象呢?原來,a鏡子裡有b鏡子的像,b鏡子裡也有a鏡子的像,這樣反反覆覆,就會產生一連串的「像中像」。這是一種遞迴現象。我們先來看乙個經典的遞迴例子:斐波那契數列(fibonacci)。為了說明這個數列,這位斐老還舉了乙個很形象的例子。
在高階語言中,呼叫自己和其他函式並沒有本質的不同。我們把乙個直接呼叫自己或通過一系列的呼叫語句間接地呼叫自己的函式,稱做遞迴函式。
函式怎麼可以自己呼叫自己?聽起來有些難以理解,不過你可以不要把乙個遞迴函式中呼叫自己的函式看做是在呼叫自己,而就當它是在呼叫另乙個函式。只不過,這個函式和自己長得一樣而已。當然,寫遞迴程式最怕的就是陷入永不結束的無窮遞迴中,所以,每個遞迴都需要乙個退出遞迴的條件。遞迴使用的是選擇結構。遞迴能使程式的結構更清晰、更簡潔、更容易讓人理解,從而減少讀懂**的時間。但是大量的遞迴呼叫會建立函式的副本,會消耗大量的時間和記憶體。那麼我們講了那麼多遞迴的內容,和棧有什麼關係呢?程式設計基礎階段我們已經了解了遞迴是如何執行它的前行和退回的。遞迴過程退回的順序是它前行順序的逆序。顯然這符合棧的儲存方式。簡單的說,就是在前行階段,對於每一層遞迴,函式的區域性變數、引數值以及返回位址都被壓如棧中。在退回階段,位於棧頂的區域性變數、引數值和返回位址被彈出,用於返**用層次中執行**的其餘部分,也就是恢復了呼叫的狀態。當然,對於現在的高階語言,這樣的遞迴問題是不需要使用者來管理這個棧的,一切都由系統代勞就可以了。
1.acm演算法:n的階乘
n的階乘意思是:從一乘到n,是乙個連續的乘法問題。其中n是自然數。
實現如下:
int fun(intn)
else
}
2.acm演算法:斐波那契數列實現
說如果兔子在出生兩個月後,就有繁殖能力,一對兔子每個月能生出一對小兔子來。假設所有兔都不死,那麼一年以後可以繁殖多少對兔子呢?
我們拿新出生的一對小兔子分析一下:第乙個月小兔子沒有繁殖能力,所以還是一對,兩個月後,生下一對小兔子數共有兩對;三個月後,老兔子又生下一對,因為小兔子還沒有繁殖能力,所以一共是三對····依次類推。
那麼很簡單就推出1,1,2,3,5,8,13····構成了乙個序列。這個數列有個十分明顯的特點,那是:前面相鄰兩項之和,構成了後一項。
int fun(int n)//計算斐波那契數列第n項的值
else
}
3.acm演算法:n的k次冪
int fun(int n,intk)
else
}
4.acm演算法:字串逆轉
void strreverse(char s,intlen)
else
}
1.進製轉換
在計算機中儲存的資料都是二進位制,所以往往需要把十進位制資料轉換成二進位制,轉換的過程實際就是除2取餘數,這其中我們可以看到最先求得餘數實際是個位數,書寫乙個資料的時候都是先書寫高位的資料,而後依次到個位。這正好和棧後進先出的特性吻合,因此可以使用棧來儲存。
例如:十進位制的25轉換成2進製
25 25/2 25%2 n 0==n/2 y=n%2
25 12 1
12 6 0
6 3 0
3 1 1
1 0 1
根據最後得到的是高位,先除餘得到的是個位,最後得到的二進位制值是:11001
2.括號匹配
判斷乙個表示式的」(「和」)」是否匹配,思路是這樣的:遇到」(「則入棧,遇到」)」則從棧頂彈出」(「與之配成一對,當整個表示式掃瞄完畢時:
(1) 若棧內為空,則說明(與)是匹配的。
(2) 若表示式掃瞄完畢,棧內仍有(則說明左括號是多的。
(3) 若當)被掃瞄到,棧裡卻沒有(能彈出了,說明)多,表示式中)也是多的。
3.表示式求值
演算法思想:
(1) 首先置運算元棧opnd為空棧,表示式的起始符#為運算子棧optr的棧底元素;
(2) 依次讀入表示式中的每個字元
若運算子是『#』或棧頂是『#』,結束計算,返回opnd棧頂值。
if(是運算元) → 則push( opnd,運算元);
if(是運算子) → 則與optr棧頂元素進行比較,按優先順序進行操作;
優先順序操作細則如下:
① if棧頂元素《輸入算符,則算符壓入optr棧,並接收下一字元
② if棧頂元素=運算子但≠『#』,則脫括號(彈出左括號)並收下一字;
③ if棧頂元素》運算子,則退棧、按棧頂計算,將結果壓入opnd棧。
④ 且該未入棧的運算子要保留,繼續與下乙個棧頂元素比較!
表示式求值過程的描述:3*(7 – 2 )
/*note:your choice is c ide
*/#include
"stdio.h
"#include
"stdlib.h
"int
e;#define max 5
struct
person;
struct
stack1s1;
struct
stack2s2;
void
menu1()
void
menu2()
void
push1()
else
}void
pop1()
else
}void
push2()
else
}void
pop2()
else
}void
fun1()
for(i=0;i<=s1.top;i++)
break
;
case4:
flag=1
;
break
; }
if(flag==1
)
}}void
fun2()
for(i=s2.front;i!=s2.rear;i=(i+1)%max)
break
;
case4:
flag=1
;
break
; }
if(flag==1
)
}}void
main()
}}
資料結構 棧應用
一 算術表示式的中綴表示 把運算子放在參與運算的兩個運算元中間的算術表示式稱為中綴表示式。例如 2 3 4 6 9 算術表示式中包含了算術運算子和算術量 常量 變數 函式 而運算子之間又存在著優先順序,不能簡單地進行從左到右運算,編譯程式在求值時,不能簡單從左到右運算,必須先算運算級別高的,再算運算...
資料結構 棧的應用
要求 首先將運算元棧opnd設為空棧,而將 作為運算子棧opter的棧底元素,這樣的目的是判斷表示式是否求值完畢 2 依次讀入表示式的每個字元,表示式須以 結尾,若是運算元則入棧opnd,若是運算子,則將此運算子c與opter的棧頂元素top比較優先順序後執行相應的操作,具體操作如下 i 若top的...
資料結構 棧的應用
棧是限制插入和刪除只能在乙個位置上進行的表,該位置是表的末端,也叫做棧頂。對棧的操作有進棧和出棧,進棧也叫做插入,出棧也就是刪除最後插入的元素。因此棧也被稱作lifo 後進先出 表。棧通常有兩種實現方式,陣列實現和鍊錶實現。下面是棧的兩個小應用demo 字串逆序 由於棧後進先出的特性,所以棧可以用於...