下图是栈和队列的实现关系:
从上图中,我们可以得知,队列是一个接口,而栈是一个实现类,对于它两的实现与原理将在后面详细介绍。本节主要说一下队列这种数据结构。
一、实现与继承关系:
首先,我们先来认识一下有关队列的接口和实现类:
1)Deque是实现Queue接口的一个双端队列
2)LinkedList是实现了List和Deque接口的一个实现类
见下面源码:
3)PriorityQueue是实现了Queue接口的优先级队列
二、Queue的使用
1、Queue作为一个接口,可以通过实现类向上转型new一个队列
Queue<TreeNode> queue=new LinkedList<>();
2、Queue的基础API
由于Queue是实现了Collection接口,可以调用父类的方法:isEmpty():判断空也可以使用,见下面代码所示:
public static void main(String[] args) {
Queue<Integer> queue=new LinkedList<>();
queue.offer(2);
System.out.println( queue.isEmpty() );//false
}
3、自己实现一个Queue
class Node {
int val;
Node next;
Node(int val, Node next) {
this.val = val;
this.next = next;
}
Node(int val) {
this(val, null);
}
}
public class MyQueue {
private Node head = null;
private Node tail = null;
private int size = 0;
//尾插
public void offer(int v) {
Node node = new Node(v);
if (tail == null) {
head = node;
} else {
tail.next = node;
}
tail = node;
size++;
}
//删除队首元素
public int poll() {
if (size == 0) {
throw new RuntimeException("队列为空");
}
Node oldHead = head;
head = head.next;
if (head == null) {
tail = null;
}
size--;
return oldHead.val;
}
//获取队首元素
public int peek() {
if (size == 0) {
throw new RuntimeException("队列为空");
}
return head.val;
}
//判断是否为空:原队列里边没有该方法
public boolean isEmpty() {
return size == 0;
}
//获取队列元素个数
public int size() {
return size;
}
}
三、Deque的使用与实现
Deque是实现Queue的有一个接口,是一个双端队列;双端队列指的是允许两端进行入队和出队操作。
1、Deque的使用
Deque<TreeNode> deque=new LinkedList<>();
//队首入队
deque.addFirst(root.left);
//对尾入队
deque.addLast(root.right);
2、Deque与Queue类似都有入队、出队、获取队首元素等方法,不过Deque是可以两端进行的。
判断是否为空与上面 Queue类似:isEmpty()
3、例题:剑指 Offer 28. 对称的二叉树
【题目描述】:请实现一个函数,用来判断一棵二叉树是不是对称的。如果一棵二叉树和它的镜像一样,那么它是对称的。
例如,二叉树 [1,2,2,3,4,4,3] 是对称的。
思路:借助队列类似于层序遍历,但此时需要LinkedList因为她插入的时候能够插入空(某个节点的左右孩子可能为空),并且是双向链表。
代码:
import java.util.Deque;
import java.util.LinkedList;
class Solution {
public boolean isSymmetric(TreeNode root) {
if(root ==null)
{
return true;
}
Deque<TreeNode> deque=new LinkedList<>();
deque.addFirst(root.left);
deque.addLast(root.right);
while(!deque.isEmpty())
{
TreeNode leftNode=deque.removeFirst();
TreeNode rightNode=deque.pollLast();
//当前比较的左右节点都为空,继续遍历
if(leftNode==null && rightNode==null)
{
continue;
}
if(leftNode==null || rightNode==null)
{
return false;
}
if(leftNode.val!=rightNode.val)
{
return false;
}
deque.addFirst(leftNode.right);
deque.addFirst(leftNode.left);
deque.addLast(rightNode.left);
deque.addLast(rightNode.right);
}
return true;
}
}