队列实现栈 | 栈实现队列
隊列實現(xiàn)棧 | 棧實現(xiàn)隊列
?、 ?棧實現(xiàn)隊列
首先,隊列的 API 如下:
class MyQueue {/** 添加元素到隊尾 */public void push(int x);/** 刪除隊頭的元素并返回 */public int pop();/** 返回隊頭元素 */public int peek();/** 判斷隊列是否為空 */public boolean empty(); }我們使?兩個棧 s1, s2 就能實現(xiàn)?個隊列的功能(這樣放置棧可能更容易理解) :
class MyQueue {private Stack<Integer> s1, s2;public MyQueue() {s1 = new Stack<>();s2 = new Stack<>();}// ... }當調用 push 讓元素入隊時,只要把元素壓入 s1 即可,比如說 push 進 3 個元素分別是 1,2,3,那么底層結構就是這樣:
/** 添加元素到隊尾 */ public void push(int x) {s1.push(x); }那么如果這時候使用 peek 查看隊頭的元素怎么辦呢?按道理隊頭元素應該是 1,但是在 s1 中 1 被壓在棧底,現(xiàn)在就要輪到 s2 起到一個中轉的作用了:當 s2 為空時,可以把 s1 的所有元素取出再添加進 s2,這時候 s2 中元素就是先進先出順序了。
/** 返回隊頭元素 */ public int peek() {if (s2.isEmpty())// 把 s1 元素壓入 s2while (!s1.isEmpty())s2.push(s1.pop());return s2.peek(); }同理,對于 pop 操作,只要操作 s2 就可以了
/** 刪除隊頭的元素并返回 */ public int pop() {// 先調用 peek 保證 s2 非空peek();return s2.pop(); }最后,如何判斷隊列是否為空呢?如果兩個棧都為空的話,就說明隊列為空:
/** 判斷隊列是否為空 */ public boolean empty() {return s1.isEmpty() && s2.isEmpty(); }C++代碼:
class MyQueue { public: //主要思想是定義兩個棧,一個用來存放入隊元素的棧s1,另一個棧 //用來進行出隊操作的s2,往隊列中插元速時,直接往s1中插入,出隊時, //如果s2不為空,直接在s2中進行出棧操作,如果s2為空,就把s1中元素全部放到s2中/** Initialize your data structure here. */MyQueue() {}/** Push element x to the back of queue. */void push(int x) {//直接往s1中插入s1.push(x);}/** Removes the element from in front of queue and returns that element. */int pop() {//進行出隊操作時,如果s2為空,就直接把s1中元素先移動到s2中,//在進行出隊操作,如果s2不為空,直接在s2中直接出隊,注意不能在s2有//元素時把s1中的元素移動到s2中,這樣順序回亂int data;if(s2.empty()){while(s1.size()){s2.push(s1.top());s1.pop();}data = s2.top();s2.pop();}else{data = s2.top();s2.pop();}return data;}/** Get the front element. */int peek() {int data;if(s2.empty()){while(s1.size()){s2.push(s1.top());s1.pop();}data = s2.top();//s2.pop();}else{data = s2.top();//s2.pop();}return data;}/** Returns whether the queue is empty. */bool empty() {return s1.empty() && s2.empty();}private:stack<int> s1;stack<int> s2; };二、用隊列實現(xiàn)棧
首先看下棧的 API:
class MyStack {/** 添加元素到棧頂 */public void push(int x);/** 刪除棧頂?shù)脑夭⒎祷?*/public int pop();/** 返回棧頂元素 */public int top();/** 判斷棧是否為空 */public boolean empty(); }先說 push API,直接將元素加入隊列,同時記錄隊尾元素,因為隊尾元素相當于棧頂元素,如果要 top 查看棧頂元素的話可以直接返回:
class MyStack {Queue<Integer> q = new LinkedList<>();int top_elem = 0;/** 添加元素到棧頂 */public void push(int x) {// x 是隊列的隊尾,是棧的棧頂q.offer(x);top_elem = x;}/** 返回棧頂元素 */public int top() {return top_elem;} }我們的底層數(shù)據(jù)結構是先進先出的隊列,每次 pop 只能從隊頭取元素;但是棧是后進先出,也就是說 pop API 要從隊尾取元素。
解決方法簡單粗暴,把隊列前面的都取出來再加入隊尾,讓之前的隊尾元素排到隊頭,這樣就可以取出了:
/** 刪除棧頂?shù)脑夭⒎祷?*/ public int pop() {int size = q.size();while (size > 1) {q.offer(q.poll());size--;}// 之前的隊尾元素已經(jīng)到了隊頭return q.poll(); }這樣實現(xiàn)還有一點小問題就是,原來的隊尾元素被提到隊頭并刪除了,但是 top_elem 變量沒有更新,我們還需要一點小修改:
/** 刪除棧頂?shù)脑夭⒎祷?*/ public int pop() {int size = q.size();// 留下隊尾 2 個元素while (size > 2) {q.offer(q.poll());size--;}// 記錄新的隊尾元素top_elem = q.peek();q.offer(q.poll());// 刪除之前的隊尾元素return q.poll(); }最后,API empty 就很容易實現(xiàn)了,只要看底層的隊列是否為空即可:
/** 判斷棧是否為空 */ public boolean empty() {return q.isEmpty(); }當然可以用兩個隊列來實現(xiàn)一個棧:
C++代碼:
class MyStack { public: //主要思想是定義兩個隊列,入棧時,如果兩個隊列同時為空,就隨便往一個隊列中插入 //如果其中有一個隊列不為空,每次插就往非空的隊列中插入。出棧時,每次把非空隊列的 //前size-1個元素移動到空隊列中,原非空隊列就只剩下最后一個元素,這個元素滿 //足棧的要求,直接出隊??傊?#xff0c;主要思想是把兩個隊列中的元素來回移動,每次剩下最后 //一個元素直接出隊,就相當于是棧頂元素/** Initialize your data structure here. */MyStack() {queue<int> q1;queue<int> q2;}/** Push element x onto stack. */void push(int x) {//如果兩個隊列都為空,隨便插入到一個隊列中,反之插入到非空隊列中if(!q1.empty()){q1.push(x);}else{q2.push(x);}}/** Removes the element on top of the stack and returns that element. */int pop() {//每次把非空隊列中的前size-1個元素移動到空隊列中去,原非空隊列//剩下最后一個元素就相當于棧頂元素,出棧時,就直接出隊int data; if(q1.empty()){while(q2.size() > 1){q1.push(q2.front());q2.pop();}data = q2.front();q2.pop();}else{while(q1.size() > 1){q2.push(q1.front());q1.pop();}data = q1.front();q1.pop();}return data;}/** Get the top element. */int top() {//返回非空隊列的隊尾元素,就相當于棧頂元素,if(!q1.empty()){return q1.back();}else{return q2.back();}}/** Returns whether the stack is empty. */bool empty() {//兩個隊列同時為空是,此時才表明棧中沒有任何元素return q1.empty() && q2.empty();}private:queue<int> q1;queue<int> q2; };總結
以上是生活随笔為你收集整理的队列实现栈 | 栈实现队列的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 递归反转链表的一部分
- 下一篇: 回溯算法详解之全排列、N皇后问题