Fork me on GitHub

栈与队列相互实现

背景

一道很经典的数据结构的题目实现。

栈:一般是后进先出的顺序,可以看下java中的Stack这个类。

队列:一般是先进先出的顺序,但是java中的Queue接口中也写了注释,没有要求是必须严格的先进先出,比如java中也有优先级队列、双端队列Deque。

代码实现

在代码的注释中有描述对应的思路,这里不去赘述

  • 两个栈实现队列
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
/**
* Created by zlj on 2020/3/18.
* 两个栈 实现 队列
*
* 思路:
* 1.入栈:直接压栈进入stackOne
* 2.出栈:
* (1)判断stackOne是否为空,如果不为空,则将stackOne中的数据导入stackTwo。取出stackTwo弹栈的元素
* (2)判断stackTwo是否为空,如果不为空,重复(1)操作
*
*/
public class StackToQueue<T> {

Stack<T> stackOne = new Stack<>();
Stack<T> stackTwo = new Stack<>();

/**
* 入队
* @param data
*/
private void push(T data) {
stackOne.push(data);
}

/**
* 出队列
* @return
*/
private T pop() {
if (stackOne.empty() && stackTwo.empty())
return null; // 容错 栈的pop方法如果没有元素了会报错
// 其实加不加这个判断相当于Queue接口中poll(做了容错) 和 remove(没做容错) 两个方法的区别

while (!stackOne.isEmpty()) {
// 弹栈到stackTwo
stackTwo.push(stackOne.pop());
}

// 这时弹栈 stackTwo中的元素
T stackTwoFirstEmt = stackTwo.pop();

// 如果出队列的时候元素都在stackTwo
while(!stackTwo.isEmpty()) {
// 数据倒回stackOne 以便下一次pop的时候 再利用栈的特性 实现队列出队的顺序
stackOne.push(stackTwo.pop());
}

return stackTwoFirstEmt;
}

public static void main(String[] args) {
StackToQueue<Integer> stackToQueue = new StackToQueue<>();

// 队列入队
Stream.iterate(1, i -> i+1).limit(10).forEach(stackToQueue::push);

// 队列出队
for(int i = 0; i< 10000; i++) {
Integer pop = stackToQueue.pop();
if (pop == null) break;
System.out.println("队列出队:" + pop);
try {
Thread.sleep(200);
} catch (Exception e) {

}

}
}

}
  • 两个队列实现栈
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
/**
* Created by zlj on 2020/3/19.
* 两个队列实现栈
* 思路: 维护两个队列 Q1 和 Q2
* (1)入栈:即为队列Q1中加入元素
* (2)出栈: 关键就是保持队列q1和q2一直有一个为空
*
* - 首先元素入q1,队列中为 [tail]xn->xn-1...->x1 [head] 这时将q1中的n-1个元素入q2 q2中元素: [tail] xn-1->xn-2...->x1 [head]
* - xn从q1中出队
* - 这时q1为空,q2有n-1个元素,重复第一步,只不过现在是将q2中的n-2个元素出队放入q1中,再将q2中的xn-1出队即可。
* - 重复操作直到 q1和q2都为空为止
*/
public class TwoQueueToStack<T> {

// 这里用的Deque 虽然只是需要的是队列 先进先出(FIFO)的特性 但其实Deque既提供了stack的操作、又提供了queue的操作,也提供了对first和end的操作(LinkedList里面叫做head和tail)
Queue<T> queue1 = new ArrayDeque<>();
Queue<T> queue2 = new ArrayDeque<>();

/**
* 栈的入栈操作
* @param element
*/
void push(T element) {
queue1.offer(element); // 比add更友好
}


/**
* 栈的出栈操作
*
* @return
*/
T pop() {

if (!queue1.isEmpty()) {
while (queue1.size() > 1) {
// q1出队 入队q2
queue2.offer(queue1.poll());
}
// q1的size是1了
return queue1.poll();
}

if (!queue2.isEmpty()) {
while (queue2.size() > 1) {
queue1.offer(queue2.poll());
}
// q2的size是1了
return queue2.poll();
}

return null;
}

int size() {
if (!queue1.isEmpty()) {
return queue1.size();
} else if (!queue2.isEmpty()) {
return queue2.size();
}
return 0;
}

/**
* 实现一个只查看栈顶元素的操作
* 思路也是先将q1的n-1个元素入队q2,这时将q1中的剩余元素peek出来,不是poll出来(元素不能删除),再将其也导入到q2中
* // 注意这里如果直接用的是双端队列Deque 其实直接可以在不为空的队列中 peekLast = =
*/
@SuppressWarnings("all")
T top() {
T top = null;
if (!queue1.isEmpty()) {
while (queue1.size() > 1) {
queue2.offer(queue1.poll());
}
top = queue1.peek();
// 再将其入队至q2
queue2.offer(queue1.poll());
}

if (!queue2.isEmpty()) {
while (queue2.size()>1) {
queue1.offer(queue2.poll());
}

top = queue2.peek();
queue1.offer(queue2.poll());
}

return top;
}




public static void main(String[] args) {

TwoQueueToStack<Integer> twoQueueToStack = new TwoQueueToStack<>();

// 压栈
Stream.iterate(1, i -> i+1).limit(10).forEach(twoQueueToStack::push);

// 查看栈顶的元素
System.out.println("栈顶元素:" + twoQueueToStack.top());

// 出栈
int size = twoQueueToStack.size();
for (int i = 0; i <size; i++) { // 注意这里不能写成 i < twoQueueToStack.size() 因为循环中的pop操作会减少stack中的元素
System.out.println("元素出栈" + twoQueueToStack.pop());
}
}
}
-------------本文结束感谢您的阅读-------------

本文标题:栈与队列相互实现

文章作者:夸克

发布时间:2020年03月22日 - 22:03

最后更新:2022年07月01日 - 06:07

原始链接:https://zhanglijun1217.github.io/2020/03/22/栈与队列相互实现/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。