1. 程式人生 > >《演算法》1.3.49用棧表示佇列,練習題學習小結

《演算法》1.3.49用棧表示佇列,練習題學習小結

《演算法》1.3.49用棧表示佇列,練習題學習小結

《演算法(第四版)》1.3.49:棧與佇列。用有限個棧實現一個佇列,保證每個佇列(在最壞的情況下)都只需要常數次的棧操作。換言之,用若干個後進先出的棧表示一個先進先出的佇列。

思路a:有兩個棧s和st,s視為棧,st視為佇列,st.push(s.pop())實現item排列順序的變換。新增item時,item先進入棧s,再通過對應關係重置“佇列”st;刪除item時,item先從“佇列”st彈出,再通過對應關係重置棧s。對s和st的重置需要用到棧的複製。

閱讀了這篇部落格後又有了如下總結https://blog.csdn.net/synapse7/article/details/18133787


思路b:思路a實際上用了四個棧,轉換的時候對棧的遍歷次數過多,棧s和st的利用率低。可以考慮聯用棧s和棧st一起表示佇列。將棧s視為佇列的逆序,st作為緩衝區,入隊時,item直接壓入s;出隊時,將s中的item逐個倒入st,完成後彈出st頂部的item,再將st的item倒回s。所以s和st要麼為空,要麼為滿。
在這裡插入圖片描述
思路c:思路b中棧s和棧st的聯用效率低,有些“倒回”操作是多餘的。如果連續進行出隊操作,則無需將st倒回s。所以有在入隊操作前判斷s是否為空,若為空,則將st倒回s;在出隊操作前判斷st是否為空,若為空,則將s倒入st。

思路d:考慮到st中的item總是s倒入的,假設在“倒出”操作完成後,直接往s中壓入新的item,會發現st中的item重要先於s中的item入隊,故在st完全為空後,可以再進行“倒出”操作。簡言之,不論s是否為空,可以直接進行item壓入。Java程式如下

public class QueueStack<Item> {

	private Stack<Item> s = new Stack<Item>();
	private Stack<Item> st = new Stack<Item>();
	
	public boolean isEmpty() {
		return st.isEmpty() && s.isEmpty();
	}
	public int size() {
		return st.size() + s.size();
	}

	public void
enqueue(Item item) { //像表尾新增元素 /***思路c if(s.isEmpty()) { //非空即滿 while(!st.isEmpty()) { s.push(st.pop()); } s.push(item); } else { s.push(item); } **/ s.push(item); } public Item dequeue() { //從表頭刪除元素 if(st.isEmpty()) { //非空即滿 while(!s.isEmpty()) { st.push(s.pop()); } return st.pop(); } else { return st.pop(); } } }