数据结构-简单队列实现
目录
某个公司的客户热线火爆,拨打的人数一旦过多,拨打电话的人员就需要进入等待队伍进行排队,公司客户按照先排队先接通进行接通。
简单队列
每个拨打电话的人员抽象为一个节点,严格按照顺序进行排队形成一个队伍,出队时严格按照先进先出原则出队,这样形成的数据结构成为队列。对于简单队列,可以使用单向链表实现。出队时将 head 节点出队, 新节点在 tail 之后入队。主要提供出队和入队操作。
Class SingleLinkedQueue<E>
属性概述
作用域和类型 | 属性和描述 | 备注 |
---|---|---|
private final Node | head 标识队列头位置 |
出队时将 head 节点出队 |
private final Node | tail 标识队列末尾位置 |
新节点在 tail 之后入队 |
private int | size 记录队列长度 |
添加节点 +1 删除节点 -1 |
static final class | Node 内部节点类 |
拥有 next 指针域和 data 数据域 |
方法概述
作用域和类型 | 函数和描述 | 备注 |
---|---|---|
public void | enqueue(E e) 入队操作 |
该节点在链表末尾添加 |
public E | dequeue() 出队操作 |
在链表头部出队 |
public int | getSize() 获取队列长度 |
返回属性 size 当前值 |
public void | print() 打印队列 |
用于调试 |
public boolean | isEmpty() 判断队列为空 |
|
public void clear() | clear() 清空队列数据 |
关键操作步骤
使用链表实现队列,只需保证头尾标识 head 和 tail 始终保持在链表的头部和尾部,出队和入队都围绕这两个部位进行操作即可。
入队操作
对于单向链表实现队列来说,由于 tail 永远指向链表的尾部,所以只需要将新的节点往尾部追加即可。这里有两种情况:链表为空/链表非空。
第一种情况:链表为空时
第一步:将 head 移动到 newNode;
第二步:将 tail 移动到 head,此时 head 和 tail 同时指向 newNode;
第二种情况:链表非空时
第一步:将 tail 的 next 指向 newNode;
第二步:将 tail 移动到 newNode ,tail 永远指向最后一个节点;
public void enqueue(E e) {
Node newNode = new Node(e);
if (isEmpty()) {
head = newNode;
tail = head;
} else {
tail.next = newNode;
tail = newNode;
}
size++;
}
出队操作
对于单向链表实现队列来说,出队在头部进行,需要将 head 移动到下一个节点。
第一步:将 head 使用 delNode 保存起来;
第二步:将 head 移动到下一个节点;
第三步:delNode 的 next 指向指为空 ;
public E dequeue() {
if (isEmpty()) return null;
Node<E> deNode = head;
head = head.next;
deNode.next = null;
size--;
return deNode.data;
}
编码实现
interface Queue<E>
package com.skystep.数据结构和算法.队列;
public interface Queue<E> {
//获取队列中元素个数
int getSize();
//队列中元素是否为空
boolean isEmpty();
//入队列
void enqueue(E e);
//出队列
public E dequeue();
// 清空链表
void clear();
void print();
}
class LinkedListQueue<E>
package com.skystep.数据结构和算法.队列;
public class LinkedListQueue<E> implements Queue<E> {
private Node head;
private Node tail;
private int size;
@Override
public int getSize() {
return size;
}
@Override
public boolean isEmpty() {
return size == 0;
}
@Override
public void enqueue(E e) {
Node newNode = new Node(e);
if (isEmpty()) {
head = newNode;
tail = head;
} else {
tail.next = newNode;
tail = newNode;
}
size++;
}
@Override
public E dequeue() {
if (isEmpty()) return null;
Node<E> deNode = head;
head = head.next;
deNode.next = null;
size--;
return deNode.data;
}
@Override
public void clear() {
head = tail = null;
size = 0;
}
@Override
public void print() {
StringBuilder res = new StringBuilder();
res.append("Queue: ");
Node<E> cur = head;
while (cur != null) {
res.append(cur.data + " ");
cur = cur.next;
}
System.out.println(res);
}
static final class Node<E> {
private Node next = null;
private E data = null;
public Node() {
}
public Node(E data) {
this.data = data;
}
public Node(Node next, E data) {
this.next = next;
this.data = data;
}
}
}
class Client
package com.skystep.数据结构和算法.队列;
public class Client {
public static void main(String[] args) {
Queue queue = new LinkedListQueue();
for (int i = 0; i < 10; i++) {
queue.enqueue(i);
}
System.out.println("队列长度是:" + queue.getSize());
queue.print();
System.out.print("出队的顺序是:");
for (int i = 0; i < 10; i++) {
Integer val = (Integer) queue.dequeue();
System.out.print(val + " ");
}
System.out.println();
System.out.println("队列长度是:" + queue.getSize());
queue.enqueue(1);
queue.enqueue(2);
System.out.println("队列长度是:" + queue.getSize());
queue.clear();
System.out.println("队列长度是:" + queue.getSize());
}
}