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