目录
- 队列的定义
- 队列的链式存储结构
- 队列的类创建
- 定义结点
- 成员变量和初始化(构造器constructor)
- 队列的基本操作
- 元素入队(add)
- 元素出队(remove)
- 读取队头元素(peek)
- 非空判断(isEmpty)
- 全部代码
队列的定义
队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(head)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。
它是一种先进先出(First In First Out)的线性表,简称FIFO。
允许插入的一端称为队尾(rear/tail/back),允许删除的一端称为队头(head/front)。
如图,新元素入队时,在队列的尾端进行入队Enqueue;
队列中的元素想出队时,在队列的头部进行出队Dequeue。
队列的链式存储结构
在队列的形成过程中,可以利用线性链表的原理,来生成一个队列。
基于链表的队列,要动态创建和删除节点,效率较低,但是可以动态增长。
队列的类创建
定义结点
要使用链式存储结构来实现队列我们首先需要定义我们的结点类:
public class Node<T> {
public T data;
public Node<T> next;
Node(){
}
Node(T data, Node<T> next){
this.data = data;
this.next = next;
}
Node(T data) {
this.data = data;
next = null;
}
}
成员变量和初始化(构造器constructor)
在链式存储结构的队列中,我们需要创建出head和rear两结点来分别代表队列的头部和尾部。
当初始化一个新的queue队列时,队列内部是空的,但是一个正确的队列中头部指针指向队列的第一个节点,而尾部指针指向队列的最后一个节点。
为此我们需要在构造器中把头指针和尾指针相连。
private Node<T> head = new Node<T>(); //头结点
private Node<T> rear = new Node<T>(); //尾结点,初始化时亦作首元结点
public int length = 0;
public Queue_List() {
head.next = rear;
}
队列的基本操作
元素入队(add)
/**
* 元素入队
* @param item 入队元素
*/
public void add(T item) {
if (isEmpty()) {
rear = new Node<>(item);
head.next = rear;
} else {
rear.next = new Node<>(item);
rear = rear.next;
}
length++;
}
元素出队(remove)
解释:head 向队伍后面移动一位结点,原结点由java自带的garbage collector 清理掉
/**
* 元素出队
* @return 元素出队
* @throws Exception 队空
*/
public T remove() throws Exception {
if (isEmpty()) throw new Exception("Queue is empty");
head = head.next;
length--;
return head.data;
}
读取队头元素(peek)
/**
* 读取队头元素
* @return 队头元素
* @throws Exception 队空
*/
public T peek() throws Exception {
if (isEmpty()) throw new Exception("Queue is empty");
return head.data;
}
读取队头元素(peek)
/**
* 非空判断
* @return 非空为true
*/
public boolean isEmpty() {
return length == 0;
}
非空判断(isEmpty)
/**
* 非空判断
* @return 非空为true
*/
public boolean isEmpty() {
return length == 0;
}
全部代码
public class Queue_List<T> implements QueueInterface<T>{
private Node<T> head = new Node<T>(); //头结点
private Node<T> rear = new Node<T>(); //尾结点,初始化时亦作首元结点
public int length = 0;
public Queue_List() {
head.next = rear;
}
/**
* 元素入队
* @param item 入队元素
*/
public void add(T item) {
if (isEmpty()) {
rear = new Node<>(item);
head.next = rear;
} else {
rear.next = new Node<>(item);
rear = rear.next;
}
length++;
}
/**
* 元素出队
* @return 元素出队
* @throws Exception 队空
*/
public T remove() throws Exception {
if (isEmpty()) throw new Exception("Queue is empty");
head = head.next;
length--;
return head.data;
}
/**
* 读取队头元素
* @return 队头元素
* @throws Exception 队空
*/
public T peek() throws Exception {
if (isEmpty()) throw new Exception("Queue is empty");
return head.data;
}
/**
* 非空判断
* @return 非空为true
*/
public boolean isEmpty() {
return length == 0;
}
/**
* 顺序打印
*/
public void printAll() {
if (isEmpty()) {
System.out.println("Stack is empty!");
return;
}
String toPrint = "";
Node<T> iter = head.next;
for (int i = 1; i <= length; i++) {
toPrint = toPrint + " " + iter.data;
iter = iter.next;
}
System.out.println("Queue: " + toPrint);
}
/**
* 按索引顺序查找元素
* @param pos 元素索引
* @return pos索引对应元素
*/
public T search(int pos) {
Node<T> iter = head.next;
for (int i = 1; i < pos; i++) {
iter = iter.next;
}
return iter.data;
}
//test
public static void main(String[] args) throws Exception {
Queue_List<Integer> queue = new Queue_List<Integer>();
queue.add(2);
queue.add(3);
queue.add(4);
queue.add(5);
System.out.println(queue.length);
queue.printAll();
System.out.println(queue.remove());
System.out.println(queue.remove());
queue.printAll();
System.out.println(queue.search(3));
}
}