日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

数据结构九——栈

發(fā)布時間:2023/12/10 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 数据结构九——栈 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

文章出處:極客時間《數(shù)據(jù)結構和算法之美》-作者:王爭。該系列文章是本人的學習筆記。

1棧的定義

1.1 棧的定義

棧:后進者先出,先進著后出。就像一碟盤子,如果拿走一個盤子,拿走的一定是最后放上去的那個。棧是一種操作受限的線性表,只允許在一端插入和刪除。本質上來說就是一個操作不方便的數(shù)組或者鏈表。

棧存在的意義是什么?數(shù)據(jù)結構本身就是對特定場景的抽象,要求操作不多不少,正好滿足場景需求。過多的接口會帶來操作不可控,進而操作結果不可預計。

1.2 實現(xiàn)棧

我們可以使用數(shù)組實現(xiàn)一個棧,稱為順序棧;也可以用鏈表實現(xiàn)一個棧,稱為鏈式棧。

/*** 數(shù)組實現(xiàn)的棧,在一端插入和刪除,那就對數(shù)組的最后一個元素操作吧*/ public class ArrayStack {//存儲數(shù)據(jù)的值private int[] items;//容量private int n;//存儲元素個數(shù)private int size;/**** @param capacity* 容量*/public ArrayStack(int capacity){this.n = capacity;items = new int[n];}/*** 添加元素,如果還有空間則添加成功,返回true。否則返回false。* @param val* @return*/public boolean push(int val){if(this.size >=n) return false;items[size++] = val;return true;}/*** 棧內元素個數(shù)* @return*/public int size(){return this.size;}/*** 刪除棧頂元素。如果當前棧內沒有元素,則拋出異常。在調用pop之前先調用size()吧。* @return*/public int pop(){if(size==0) throw new IllegalArgumentException("棧目前沒有任何元素,不能彈出元素");return items[--size];} }

復雜度分析。push,pop時間復雜度為O(1),即使鏈表實現(xiàn)的棧也一樣。空間復雜度式O(n)。需要大小為n的數(shù)組存儲棧內元素。

1.3 支持動態(tài)擴容的棧

上面的實現(xiàn)中,當棧內沒有空間的時候,就不能再插入元素。如果實現(xiàn)一個空間不受限的棧呢?這是一個數(shù)組自動擴容、自動減少空間的過程。我們只需要判斷在數(shù)組滿了的時候申請一個2倍容量的數(shù)組,將原有元素拷貝過去。

當棧內元素只有數(shù)組容量1/4的時候,將數(shù)組容量縮小到一半。當然對內存空間不敏感的應用可以不用做這一步。

/*** 添加元素* @param val*/public void push(int val){if(this.size >=n) {grow();}items[size++] = val;}private void grow() {int newSize = 2*size;int[] newItmes = new int[newSize];System.arraycopy(this.items,0,newItmes,0,size);this.n = newItmes.length;this.items = newItmes;}

接下來我們分析一下支持動態(tài)擴容的棧入棧時間復雜度是多少。入棧操作的平均時間復雜度用攤還分析法。為了分析方便,我們先做以下假設:
1 只有擴容操作,擴容為原來數(shù)組2倍大小;
2 只有push,沒有pop操作;
3 定義不涉及內存搬移的入棧操作為simple-push。

如果當前數(shù)組大小為K,當再有新的數(shù)據(jù)入棧的時候,需要申請一個大小為2K的數(shù)組,并且有K次數(shù)據(jù)遷移的操作。但是接下來的K-1次入棧操作,就無需申請內存和遷移數(shù)據(jù)。

如圖所示,第K次入棧,需要的K次遷移操作,可以均攤到到未來K-1次入棧操作。所以這K次操作,平均下來每次是一次數(shù)據(jù)遷移和一個simple-push。時間復雜度O(1)。

2棧的應用

2.1 棧在函數(shù)調用中的應用

2.2 棧在表達式求值中的應用

2.3 棧在括號匹配中的應用

3 瀏覽器支持前進后退操作

瀏覽器前進、后退操作是這樣的。當你訪問頁面 a->b->c之后,你可以按后退按鈕回到頁面b,再繼續(xù)按前進按鈕到頁面c。

我們使用兩個棧X、Y來完成瀏覽器的前進后退操作。當訪問頁面的時候,我們按照順序將頁面入棧X。當按后退按鈕的時候,從X棧取出元素,入棧Y。當按前進按鈕的時候,從Y棧取出元素,入棧X。當X棧為空的時候,后退按鈕不能用。當Y棧為空的時候,前進按鈕不能用。

例如初始:
X
Y

訪問頁面a:
X:a
Y

訪問頁面b:
X:a,b
Y
訪問頁面c:
X:a,b,c
Y

按后退按鈕,展示頁面b:
X:a,b
Y:c

按后退按鈕,展示頁面a:
X:a
Y:c,b

按前進按鈕,從頁面a到頁面b:
X:a,b
Y:c

這個時候,你訪問了新頁面d,這時候前進按鈕應該不能用,因為d的下一個頁面還沒有產(chǎn)生;按后退按鈕的話應該回到b;所以c頁面不能通過前進后退轉到,需要清空Y棧:
X:a,b,d
Y:

4 思考

Java虛擬機中有堆棧的概念。棧內用來存儲臨時變量和方法調用,堆內存儲Java對象。那么Java虛擬機中的棧和這里的棧,概念一樣嗎?
答:不一樣。數(shù)據(jù)結構中的棧是對場景的抽象,是抽象的數(shù)據(jù)機構。
JVM使用的內存分為代碼區(qū)、靜態(tài)數(shù)據(jù)區(qū)和動態(tài)數(shù)據(jù)區(qū)。
代碼區(qū):存放方法的二進制代碼,控制代碼區(qū)代碼執(zhí)行切換。
靜態(tài)數(shù)據(jù)區(qū):全局變量、靜態(tài)變量,常量(包含final修飾的和String)。
動態(tài)數(shù)據(jù)區(qū):分為堆區(qū)和棧區(qū)。堆區(qū)存放對象,該對象的引用存放在棧區(qū)。棧區(qū)存放運行方法的形參、局部變量和返回值。

總結

以上是生活随笔為你收集整理的数据结构九——栈的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內容還不錯,歡迎將生活随笔推薦給好友。