简介
栈和队列从定义上来讲,只有一个不同,就是栈是先进后出的,而队列是先进先出的,两者不的不同如下所图所示:
栈和队列的实现
从实现上来说,栈和队列都可以用数组或者链表实现,不过从实现难度和时空复杂度的角度考虑,一般来说,栈会自用数组实现,队列会用链表实现。
在Java中,常见的栈有Stack,Deque(implemented by LinkedListD),常见的队列有Queue和Queue(implemented by LinkedList)所以我们一般刷题的时候,常常会用下面的写法:
Stack<Integer>stack = new stack<>();
stack.push(1);
stack.pop();
Queue<Integer> queue = new LinkedList<>();
queue .offer(1);
queue.po11();
应用
栈和队列在日常开发过程中无处不在。
我们平常所使用的递归,就是通过栈来实现的。同时还有JM中的方法在执行的时候,也会放到栈上,因为他们的执行顺序都是遵循先进后出的
队列常常作为缓冲区来使用,像我们熟知的生产者和消费者模型,生产者完成任务后,会把数据存放到队列中,等待消费者来读取。
双端队列和循环队列
双端队列
队列还有一种变形的结构叫双端队列,所谓的双端,就是说该队列不仅道循FIFO原则,通常也可以按照使用者的想法从队首或者队尾进行插入和删除
Deque<Integer> dequenew LinkedList<>();
deque.offerFirst(1);
deque.offerLast(1);
deque.pollFirst();
deque.pollLast();
循环队列
一般情况下,数组是不能实现队列的,因为先进先出,可能会存在假溢出的情况,所以数组的空间一定会被浪费。所以,我们会通过循环的方式,当最尾部的索引到达length之后,我们会将该索引重新置为0,以此来重复利用数组的空间。而这样一种形式,就会造成一种逻辑循环,也就是我们说的循环队,假溢出如下所示:
一般来说,循环队列可以作为缓冲区使用,如果index超出,直接覆盖就可以了。