1.栈和队列概念
栈和队列是一种逻辑上的数据结构:
- "栈”(Stack)的本意是干草堆;描述一种数据后入先出 LIFO (LastInput First Out)
- “队列”(Queue)就是等待做某事而排成的队;描述一种先入先出 FIFO(First Input First Out)
参考:《计算机是怎么跑起来的》-[日]矢泽久雄 第6.4章节
2.代码实现
- 用双向链表
import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;
/**
* 双向链表实现栈和队列
*
* @author TaoistQu
*/
public class DoubleEndsQueueToStackAndQueue {
/**
* 实现一个双向链表结构,可以从头部和尾部依次添加元素
* 也可以从头部和尾部删除元素
*
* @param <T>
*/
public static class DoubleEndsQueue<T> {
public Node<T> head;
public Node<T> tail;
/**
* 从头部加节点
*
* @param value
*/
public void addFromHead(T value) {
Node<T> cur = new Node<>(value);
if (head == null) {
head = cur;
tail = cur;
} else {
cur.next = head;
head.last = cur;
head = cur;
}
}
/**
* 从尾部加节点
*
* @param value
*/
public void addFromBottom(T value) {
Node<T> cur = new Node<>(value);
if (head == null) {
head = cur;
tail = cur;
} else {
cur.last = tail;
tail.next = cur;
tail = cur;
}
}
/**
* 从头部弹出元素
*
* @return
*/
public T popFromHead() {
if (head == null) {
return null;
}
Node<T> cur = head;
if (head == tail) {
head = null;
tail = null;
} else {
head = head.next;
head.last = null;
cur.next = null;
}
return cur.value;
}
public T popFromBottom() {
if (head == null) {
return null;
}
Node<T> cur = tail;
if (tail == head) {
head = null;
tail = null;
} else {
tail = tail.last;
tail.next = null;
cur.last = null;
}
return cur.value;
}
public boolean isEmpty() {
return head == null;
}
}
/**
* 用双向链表实现栈
*
* @param <T>
*/
public static class MyStack<T> {
private DoubleEndsQueue<T> queue;
public MyStack() {
queue = new DoubleEndsQueue<>();
}
public void push(T value) {
queue.addFromHead(value);
}
public T pop() {
return queue.popFromHead();
}
public boolean isEmpty() {
return queue.isEmpty();
}
}
/**
* 用双向链表实现队列
*
* @param <T>
*/
public static class MyQueue<T> {
private DoubleEndsQueue<T> queue;
public MyQueue() {
queue = new DoubleEndsQueue<>();
}
public void push(T value) {
queue.addFromHead(value);
}
public T poll() {
return queue.popFromBottom();
}
public boolean isEmpty() {
return queue.isEmpty();
}
}
public static boolean isEqual(Integer o1, Integer o2) {
if (o1 == null && o2 != null) {
return false;
}
if (o1 != null && o2 == null) {
return false;
}
if (o1 == null && o2 == null) {
return true;
}
return o1.equals(o2);
}
public static void main(String[] args) {
int oneTestDataNum = 100;
int value = 10000;
int testTimes = 100000;
for (int i = 0; i < testTimes; i++) {
MyStack<Integer> myStack = new MyStack<>();
MyQueue<Integer> myQueue = new MyQueue<>();
Stack<Integer> stack = new Stack<>();
Queue<Integer> queue = new LinkedList<>();
for (int j = 0; j < oneTestDataNum; j++) {
int nums = (int) (Math.random() * value);
if (stack.isEmpty()) {
myStack.push(nums);
stack.push(nums);
} else {
if (Math.random() < 0.5) {
myStack.push(nums);
stack.push(nums);
} else {
if (!isEqual(myStack.pop(), stack.pop())) {
System.out.println("oops!");
}
}
}
int numq = (int) (Math.random() * value);
if (stack.isEmpty()) {
myQueue.push(numq);
queue.offer(numq);
} else {
if (Math.random() < 0.5) {
myQueue.push(numq);
queue.offer(numq);
} else {
if (!isEqual(myQueue.poll(), queue.poll())) {
System.out.println("oops!");
}
}
}
}
}
System.out.println("finish!");
}
/**
* 双向链表节点类
*
* @param <T>
*/
public static class Node<T> {
public T value;
public Node<T> last;
public Node<T> next;
public Node(T data) {
value = data;
}
}
}
用JDK的栈和队列作对数器进行100000次随机测试结果:
finish!
Process finished with exit code 0
- 用数组方式
/**
* @author TaoistQu
*/
public class RingArray {
/**
* 实现一个固定大小的栈
*/
public static class MyStack {
private int[] arr;
private int topIndex;
private final int limit;
public MyStack(int l) {
arr = new int[l];
limit = l;
}
public void push(int value) {
if (topIndex == limit) {
throw new RuntimeException("栈满了,不能再继续添加元素!!!");
}
arr[topIndex++] = value;
}
public int pop() {
if (topIndex == 0) {
throw new RuntimeException("栈空了,不能再取元素啦!!!");
}
return arr[--topIndex];
}
public boolean isEmpty() {
return topIndex == 0;
}
}
/**
* 实现一个循环队列;用size解耦pushi 和 polli队列的两个索引
*/
public static class MyQueue {
private int[] arr;
private int pushi;
private int polli;
private int size;
private final int limit;
public MyQueue(int l) {
arr = new int[l];
limit = l;
}
public void push(int value) {
if (size == limit) {
throw new RuntimeException("队列满了,不能再继续添加元素!!!");
}
size++;
arr[pushi] = value;
pushi = nextIndex(pushi);
}
public int pop() {
if (size == 0) {
throw new RuntimeException("队列空了,不能再取元素啦!!!");
}
size--;
int ans = arr[polli];
polli = nextIndex(polli);
return ans;
}
public boolean isEmpty() {
return size == 0;
}
/**
* 循环索引
*
* @param i
* @return
*/
private int nextIndex(int i) {
return i < limit - 1 ? i + 1 : 0;
}
}
public static void main(String[] args) {
//MyQueue myStack = new MyQueue(10);
MyStack myStack = new MyStack(10);
for (int i = 1; i <= 10; i++) {
myStack.push(i);
}
for (int i = 1; i <= 5; i++) {
System.out.print(myStack.pop() + " ");
}
System.out.println();
for (int i = 11; i <= 14; i++) {
myStack.push(i);
}
while (!myStack.isEmpty()) {
System.out.print(myStack.pop() + " ");
}
System.out.println();
}
}
测试栈的结果:
10 9 8 7 6
14 13 12 11 5 4 3 2 1
测试队列的结果:
1 2 3 4 5
6 7 8 9 10 11 12 13 14