定義
棧:後進先出(LIFO-last in first out):最後插入的元素最先出來。
隊列:先進先出(FIFO-first in first out):最先插入的元素最先出來。
圖示
本文通過一些簡單的算法題來帶你們更好的理解棧(Stack)和隊列(Queue)。
第一題
題目:獲取一個棧的min
定義棧的數據結構,請在該類型中實現一個能夠得到棧中所含最小元素的min函數(時間複雜度應爲O(1))。
import java.util.Stack;
/**
* @author god-jiang
* @date 2020/1/6
*/
public class GetMinStack {
//正常stack
Stack<Integer> stack = new Stack<>();
//存放min的stack
Stack<Integer> help = new Stack<>();
public void push(int node) {
stack.push(node);
if (help.isEmpty()) {
help.push(node);
} else {
//help裏面存放的都是最小值,也就是pop之後裏面是當前的最小值
int res = help.peek() > node ? node : help.peek();
help.push(res);
}
}
public void pop() {
stack.pop();
help.pop();
}
public int top() {
return stack.peek();
}
public int min() {
return help.peek();
}
}
第二題
題目:用棧實現隊列
思路:構建兩個棧(Push棧和Pop棧);將Push棧中的數據導入Pop棧中然後返回給用戶,就實現了隊列。需要注意兩個條件:①Pop棧爲空時才能往裏面倒數據。②向Pop棧倒數據必須全部倒完。
import java.util.Stack;
/**
* @author god-jiang
* @date 2020/1/6
*/
public class StackToQueue {
//用s1、s2避免代碼看起來混亂,因爲都是push和pop操作
private Stack<Integer> s1;
private Stack<Integer> s2;
public StackToQueue() {
s1 = new Stack<>();
s2 = new Stack<>();
}
public void add(int obj) {
s1.push(obj);
}
public Integer poll() {
if (s1.isEmpty() && s2.isEmpty()) {
throw new RuntimeException("empty");
}
if (s2.isEmpty()) {
while (!s1.isEmpty()) {
s2.push(s1.pop());
}
}
return s2.pop();
}
public Integer peek() {
if (s1.isEmpty() && s2.isEmpty()) {
throw new RuntimeException("empty");
}
if (s2.isEmpty()) {
while (!s1.isEmpty()) {
s2.push(s1.pop());
}
}
return s2.peek();
}
}
第三題
題目:用隊列實現棧
思路:構建兩個隊列:queue隊列和help隊列;壓入數據時數據都進queue隊列,假設隊列中進入了1、2、3、4、5,返回數據時,把1、2、3、4放入help隊列,然後拿出queue的5返回。接着把queue隊列和help隊列的引用交換。即下次返回數據還是從queue隊列拿1、2、3、放入help隊列,然後queue拿出4返回,再交換各自的引用,一直重複。
import java.util.LinkedList;
import java.util.Queue;
/**
* @author god-jiang
* @date 2020/1/6
*/
public class QueueToStack {
private Queue<Integer> queue;
private Queue<Integer> help;
public QueueToStack() {
queue = new LinkedList<>();
help = new LinkedList<>();
}
public void push(Integer e) {
queue.add(e);
}
public int pop() {
if (queue.isEmpty()) {
throw new RuntimeException("empty");
}
while (queue.size() != 1) {
help.add(queue.poll());
}
int res = queue.poll();
swap();
return res;
}
public int peek() {
if (queue.isEmpty()) {
throw new RuntimeException("empty");
}
while (queue.size() != 1) {
help.add(queue.poll());
}
int res = queue.poll();
help.add(res);
swap();
return res;
}
public void swap() {
Queue<Integer> tmp = queue;
queue = help;
help = tmp;
}
}
總結
就是把棧跟隊列的特點介紹了一下,然後用三道經典的題目來加深對棧和隊列的理解,然後附上我自己寫的代碼,都是經過測試後才附上的。有什麼問題,歡迎與我交流和討論,我的目的就是大家一起學習一起進步。