《演算法》1.3.49用棧表示佇列,練習題學習小結
阿新 • • 發佈:2019-01-13
《演算法》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();
}
}
}