08 | 栈:如何实现浏览器的前进和后退功能?
棧
后進者先出,先進者后出,這就是典型的“棧”結構。棧是一種“操作受限”的線性表,只允許在一端插入和刪除數(shù)據(jù)。
為什么要使用到“棧”這種操作受限的數(shù)據(jù)結構?
事實上,從功能上來說,數(shù)組或鏈表確實可以替代棧,但你要知道,特定的數(shù)據(jù)結構是對特定場景的抽象,而且,數(shù)組或鏈表暴露了太多的操作接口,操作上的確靈活自由,但使用時就比較不可控,自然也就更容易出錯。
當某個數(shù)據(jù)集合只涉及在一端插入和刪除數(shù)據(jù),并且滿足后進先出、先進后出的特性,這時我們就應該首選“棧”這種數(shù)據(jù)結構。
如何實現(xiàn)一個棧?
- 棧既可以用數(shù)組來實現(xiàn),也可以用鏈表來實現(xiàn)。
- 用數(shù)組實現(xiàn)的棧,我們叫作順序棧,
- 用鏈表實現(xiàn)的棧,我們叫作鏈式棧
順序棧的實現(xiàn):
// 基于數(shù)組實現(xiàn)的順序棧 public class ArrayStack {private String[] items; // 數(shù)組private int count; // 棧中元素個數(shù)private int n; //棧的大小// 初始化數(shù)組,申請一個大小為n的數(shù)組空間public ArrayStack(int n) {this.items = new String[n];this.n = n;this.count = 0;}// 入棧操作public boolean push(String item) {// 數(shù)組空間不夠了,直接返回false,入棧失敗。if (count == n) return false;// 將item放到下標為count的位置,并且count加一items[count] = item;++count;return true;}// 出棧操作public String pop() {// 棧為空,則直接返回nullif (count == 0) return null;// 返回下標為count-1的數(shù)組元素,并且棧中元素個數(shù)count減一String tmp = items[count-1];--count;return tmp;} }棧操作的復雜度分析
存儲數(shù)據(jù)只需要一個大小為 n 的數(shù)組就夠了。在入棧和出棧過程中,只需要一兩個臨時變量存儲空間,所以空間復雜度是 O(1);
入棧、出棧只涉及棧頂個別數(shù)據(jù)的操作,所以時間復雜度都是 O(1);
如何實現(xiàn)動態(tài)擴容的順序棧?
動態(tài)擴容的數(shù)組:當數(shù)組空間不夠時,我們就重新申請一塊更大的內(nèi)存,將原來數(shù)組中數(shù)據(jù)統(tǒng)統(tǒng)拷貝過去。這樣就實現(xiàn)了一個支持動態(tài)擴容的數(shù)組;要實現(xiàn)一個支持動態(tài)擴容的棧,我們只需要底層依賴一個支持動態(tài)擴容的數(shù)組就可以了。當棧滿了之后,我們就申請一個更大的數(shù)組,將原來的數(shù)據(jù)搬移到新數(shù)組中
棧的應用
函數(shù)調用
操作系統(tǒng)給每個線程分配了一塊獨立的內(nèi)存空間,這塊內(nèi)存被組織成“棧”這種結構, 用來存儲函數(shù)調用時的臨時變量。每進入一個函數(shù),就會將臨時變量作為一個棧幀入棧,當被調用函數(shù)執(zhí)行完成,返回之后,將這個函數(shù)對應的棧幀出棧;
代碼示例:
int main() {int a = 1; int ret = 0;int res = 0;ret = add(3, 5);res = a + ret;printf("%d", res);reuturn 0; }int add(int x, int y) {int sum = 0;sum = x + y;return sum; }編譯器通過棧實現(xiàn)求值表達式的求值
四則運算法則:34+13*9+44-12/3
編譯器就是通過兩個棧來實現(xiàn)的。其中一個保存操作數(shù)的棧,另一個是保存運算符的棧。我們從左向右遍歷表達式,當遇到數(shù)字,我們就直接壓入操作數(shù)棧;當遇到運算符,就與運算符棧的棧頂元素進行比較;如果比運算符棧頂元素的優(yōu)先級高,就將當前運算符壓入棧;如果比運算符棧頂元素的優(yōu)先級低或者相同,從運算符棧中取棧頂運算符,從操作數(shù)棧的棧頂取 2 個操作數(shù),然后進行計算,再把計算完的結果壓入操作數(shù)棧,繼續(xù)比較;
如何實現(xiàn)瀏覽器的后退和前進功能?
- 定義兩個棧X和Y,將首次瀏覽的頁面壓入棧X,當點擊后退按鈕時,再依次從棧X中出棧,并將出棧的依次壓入棧Y,當點擊前進時,就從Y中取出數(shù)據(jù)放入X中;
- 當X中沒有數(shù)據(jù)時,表示頁面不可后退,當Y中沒有數(shù)據(jù)時表示頁面不可前進;
- 當跳轉了新的頁面,新的頁面壓入棧X中,同時需要清空棧Y,也即當前頁面不可以前進了;
?
?
?
?
總結
以上是生活随笔為你收集整理的08 | 栈:如何实现浏览器的前进和后退功能?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: pytorch搭建LSTM神经网络预测电
- 下一篇: 各大浏览器兼容性报告