功能需求
一個棧依次壓入1、2、3、4、5,那麼從棧頂到棧底分別爲5、4、3、2、1.如果將這個棧經過系列轉置之後,從棧頂到棧底爲1、2、3、4、5,也就是實現棧中元素的逆序,但是隻能用遞歸函數來實現,而不是使用其他數據結構,也不能使用第二個棧。
詳細解析
在之前我們曾經使用過兩個棧操作一組數據,經過兩次壓棧出棧操作,我們可以得到逆序隊列。但是題目要求的是主要考察使用遞歸函數來設計,所以我們需要設計出兩組遞歸函數來模仿這兩個棧操作,從而實現逆序棧。
遞歸函數一:將棧stack的棧底元素返回並移除。具體實現如下代碼中的getAndRemoveLastElement方法。
代碼實現1
public static int getAndRemoveLastElement (Stack<Integer> stack) {
// 棧中彈出一個數據,並保存數據
int result = stack.pop();
// 判斷棧中元素時候爲空,如果沒有元素這返回
if (stack.isEmpty()) {
return result;
} else {
// 使用遞歸函數:調用自己本身,循環彈出棧頂元素,直到棧中無元素
int last = getAndRemoveLastElement(stack);
// 棧中依次壓入最開始彈出的數據
stack.push(result);
// 返回所存的棧數據
return last;
}
}
我們來畫個圖來分析一下這個算法的運行流程
遞歸函數二:逆序一個棧,那麼我們可以使用第二種方法,也就是題目要求的方法,具體的需要的是reserve方法。可以調用上面的getAndRemoveLastElement()方法。
代碼實現2
public static void reverse(Stack<Integer> stack) {
// 棧數據判空操作
if (stack.isEmtpy()) {
return;
}
// 調用上面的操作函數來刪除棧頂數據得到逆序結果
int i = getAndRemoveLastElement(stack);
// 遞歸調用reverse方法
reverse();
// 棧底存入棧數據
}
讓我們也來分析一下這個程序的執行流程
getAndRemoveLastElement()方法在圖中簡單表示爲get方法,表示移除並返回當前棧元素
總結分析
當我們碰到使用遞歸來操作循環的時候,一定要考慮到的兩個問題是:第一這個方法執行到什麼時候,從程序的開始到再次調用本方法的時候結束。第二就是當調用完成或者不符合條件而跳出遞歸的時候,調用本方法之後的代碼將是如何繼續運行的。其實你只需要再進行詳細分化一下,不難得出一個規律,遞歸相當於一個while(true)的死循環,也就是你如何使用break的問題,本身這個問題就是讓你熟悉瞭解遞歸算法到底是怎樣的執行流程,其實不難發現,先彈出,再彈出,彈完了之後再去運行之後的保存,就相當於你走路一樣,剛走到終點,不能直接飛回起點吧。ok今天的分享就是這...