我们去面试的时候可能排成一队等待面试,先来的排在队列前面,后来的排在队列后面,先来的先面试先走,后来的后走。队列特点:先进先出
接下来我们说一说队列在数据结构中的抽象概念。
队列的定义:
队列是限制结点插入操作固定在一端进行,而结点的删除操作固定在另一端进行的线性表.
队列的特点
先进先出型,First in first out(FIFO)
队列的基本操作
添加:给队列末尾添加一个元素
删除:队列头部中删除元素
访问:访问头部元素
动口不如动手,我们简单实现以下队列。
队列有两种实现方式
(1)基于数组的队列:长度收到限制
(2)基于链表的队列:长队不受限制
ArrayQueue的简单实现
(1)定义一个数组,并在构造方法中初始化数组长度
Object[] queue;
public ArrayQueue() {
queue = new Object[10];
}
(2)通过一个变量来表示队列中的元素数量,判断队列是否为空时判断队列元素的数量是否为0
int size;
public boolean isEmpty() {
return size == 0;
}
(3)给队列添加元素,添加元素之前要判断队列是否已满
public void add(E data) {
if(sizeelse{
throw new RuntimeException("队列不为空");
}
}
(4) 从队列张获取元素,先判断队列是否为空,如果部位空获取第0个元素,然后后面的往前copy。System.arraycopy数组复制方法。
public E poll() {
if (isEmpty()) return null;
E data = (E) queue[0];
System.arraycopy(queue, 1, queue, 0, size-1);
size--;
return data;
}
完整代码如下:
public class ArrayQueue {
Object[] queue;
int size;
public ArrayQueue() {
queue = new Object[10];
}
public boolean isEmpty() {
return size == 0;
}
public E poll() {
if (isEmpty()) return null;
E data = (E) queue[0];
System.arraycopy(queue, 1, queue, 0, size-1);
size--;
return data;
}
private void ensureCapacity(int size) {
if (size > queue.length) {
int len = queue.length + 10;
queue = Arrays.copyOf(queue, len);
}
}
public void offer(E data) {
ensureCapacity(size+1);
queue[size++] = data;
}
public void add(E data) {
if(sizeelse{
throw new RuntimeException("队列不为空");
}
}
public static void main(String[] args) {
ArrayQueue queue = new ArrayQueue<>();
for (int i = 0; i < 20; i++) {
queue.add(i);
}
for (int i = 0; i < 20; i++) {
System.out.println(queue.poll());
}
}
}
目前基于数组的队列基本完成,但是数组长度是写死的能不能改成可扩展的呢?解决这个问题有两种办法,第一采用链表队列 第二添加元素之前判断数组长度是否越界,如果有越界的风险新定义一个更长的数组,把原来的元素Copy到新的数组,新的数组中添加元素。
判断队列是否已满,如果满了长都再增加十个
private void ensureCapacity(int size) {
if (size > queue.length) {
int len = queue.length + 10;
queue = Arrays.copyOf(queue, len);
}
}
添加元素的方法如下
public void offer(E data) {
ensureCapacity(size+1);
queue[size++] = data;
}
基于链表的实现
(1) 定义节点
class Node<E> {
Node<E> next = null;
E data;
public Node(E data) {
this.data = data;
}
}
(2) 队列尾部进,头部出,我们定义两变量表示头和尾
private Node head = null;
private Node tail = null;
public boolean isEmpty() {
return head == null;
}
(3)添加元素
public void offer(E e) {
Node node = new Node(e);
if (isEmpty()) {
head = node;
tail = node;
return;
}
tail.next = node;
tail = node;
}
(4)获取元素
public E poll() {
if (isEmpty()) return null;
E data = head.data;
head = head.next;
return data;
}
(5)获取数组的长度
public int size() {
Node temp = head;
int len = 0;
while (temp != null) {
len++;
temp = temp.next;
}
return len;
}
完整代码
package demo.a_01.queue;
public class ListQueue {
class Node {
Node next = null;
E data;
public Node(E data) {
this.data = data;
}
}
private Node head = null;
private Node tail = null;
public boolean isEmpty() {
return head == null;
}
public void offer(E e) {
Node node = new Node(e);
if (isEmpty()) {
head = node;
tail = node;
return;
}
tail.next = node;
tail = node;
}
public E poll() {
if (isEmpty()) return null;
E data = head.data;
head = head.next;
return data;
}
public int size() {
Node temp = head;
int len = 0;
while (temp != null) {
len++;
temp = temp.next;
}
return len;
}
public static void main(String[] args) {
ListQueue queue = new ListQueue<>();
queue.offer("a");
queue.offer("b");
System.out.println(queue.poll());
System.out.println(queue.poll());
}
}