佇列實現棧以及棧實現佇列

2022-10-10 17:15:14 字數 3224 閱讀 1059

232.用棧實現佇列(簡單)

225.用佇列實現棧(簡單)

佇列是一種先進先出的資料結構,棧是一種先進後出的資料結構,形象一點就是這樣:

這兩種資料結構底層其實都是陣列或者鍊錶實現的,只是 api 限定了它們的特性,那麼今天就來看看如何使用「棧」的特性來實現乙個「佇列」,如何用「佇列」實現乙個「棧」。

首先,佇列的 api 如下:

classmyqueue

我們使用兩個棧s1, s2就能實現乙個佇列的功能(這樣放置棧可能更容易理解):

}當呼叫push讓元素入隊時,只要把元素壓入s1即可,比如說push進 3 個元素分別是 1,2,3,那麼底層結構就是這樣:

/** 新增元素到隊尾 */

publicvoidpush(intx)

那麼如果這時候使用peek檢視隊頭的元素怎麼辦呢?按道理隊頭元素應該是 1,但是在s1中 1 被壓在棧底,現在就要輪到s2起到乙個中轉的作用了:當s2為空時,可以把s1的所有元素取出再新增進s2,這時候s2中元素就是先進先出順序了。

/** 返回隊頭元素 */

publicintpeek()

同理,對於pop操作,只要操作s2就可以了。

/** 刪除隊頭的元素並返回 */

publicintpop()

最後,如何判斷佇列是否為空呢?如果兩個棧都為空的話,就說明隊列為空:

/** 判斷佇列是否為空 */

publicbooleanempty()

至此,就用棧結構實現了乙個佇列,核心思想是利用兩個棧互相配合。

值得一提的是,這幾個操作的時間複雜度是多少呢?有點意思的是peek操作,呼叫它時可能觸發while迴圈,這樣的話時間複雜度是 o(n),但是大部分情況下while迴圈不會被觸發,時間複雜度是 o(1)。由於pop操作呼叫了peek,它的時間複雜度和peek相同。

像這種情況,可以說它們的最壞時間複雜度是 o(n),因為包含while迴圈,可能需要從s1s2搬移元素。

但是它們的均攤時間複雜度是 o(1),這個要這麼理解:對於乙個元素,最多隻可能被搬運一次,也就是說peek操作平均到每個元素的時間複雜度是 o(1)。

如果說雙棧實現佇列比較巧妙,那麼用佇列實現棧就比較簡單粗暴了,只需要乙個佇列作為底層資料結構。首先看下棧的 api:

classmystack

先說pushapi,直接將元素加入佇列,同時記錄隊尾元素,因為隊尾元素相當於棧頂元素,如果要top檢視棧頂元素的話可以直接返回:

classmystack

/** 返回棧頂元素 */

publicinttop()

}

我們的底層資料結構是先進先出的佇列,每次pop只能從隊頭取元素;但是棧是後進先出,也就是說popapi 要從隊尾取元素:

解決方法簡單粗暴,把佇列前面的都取出來再加入隊尾,讓之前的隊尾元素排到隊頭,這樣就可以取出了:

/** 刪除棧頂的元素並返回 */

publicintpop()

// 之前的隊尾元素已經到了隊頭

return q.poll();

}

這樣實現還有一點小問題就是,原來的隊尾元素被提到隊頭並刪除了,但是top_elem變數沒有更新,我們還需要一點小修改:

/** 刪除棧頂的元素並返回 */

publicintpop()

// 記錄新的隊尾元素

top_elem = q.peek();

q.offer(q.poll());

// 刪除之前的隊尾元素

return q.poll();

}

最後,apiempty就很容易實現了,只要看底層的佇列是否為空即可:

/** 判斷棧是否為空 */

publicbooleanempty()

很明顯,用佇列實現棧的話,pop操作時間複雜度是 o(n),其他操作都是 o(1)​。​

個人認為,用佇列實現棧是沒啥亮點的問題,但是用雙棧實現佇列是值得學習的。

從棧s1搬運元素到s2之後,元素在s2中就變成了佇列的先進先出順序,這個特性有點類似「負負得正」,確實不太容易想到。

希望本文對你有幫助。

佇列實現棧棧實現佇列

佇列是一種先進先出的資料結構,要想實現先進後出,需加乙個輔助佇列進行資料的來回倒 引用交換 從而實現棧結構。例如 5 4 3 2 1 用乙個輔助佇列裝 4 3 2 1,把5彈出,在把 4 3 2 1放回原佇列,如此反覆可變成5 4 3 2 1的棧結構。棧是一種先進後出的資料結構,要想實現先進先出,同...

佇列實現棧,棧實現佇列

兩個佇列實現棧 每次進入乙個佇列,取出得時候,把所有元素進入另乙個佇列,只留下乙個元素,以此實現棧的先進後出 filo package algorithmbymyself import j a.util.linkedlist import j a.util.queue 用兩個佇列實現乙個棧 publ...

佇列實現棧棧

使用佇列實現棧的下列操作 push x 元素 x 入棧 pop 移除棧頂元素 top 獲取棧頂元素 empty 返回棧是否為空 思路 雙佇列實現 壓入建兩個空列 核心 相當於翻轉 給乙個值,壓入a,再把b 尾刪 的值壓入 a頭插 交換 a b 輸出b列 b實際值 儲存順序 與輸入的相反 輸入 1 2...