队列基本概念
队列是只允许在队尾插入元素,队头删除元素的线性表;其操作特点是 先进先出。队列有两种实现方式:链队列和循环队列。
链队列是用一组任意的存储单元来存储队列中的元素,同时设置变量 front 和 rear,front指向队列中的第一个节点,rear指向队列的最后一个节点。
循环队列是用一组连续的存储单元来存储队列中的元素,同时设置变量 front 和 rear,front表示队头元素的下标,rear表示队尾元素后一个元素的下标。
代码实现
循环队列
定义一个 CircleArrayQueue类,一个 CircleArrayQueue对象就代表一个队列。同时在该类中定义关于队列的基本操作方法
class CircleArrayQueue {
private int maxSize; //队列最大容量
private int front; //指向队列首节点
private int rear; //指向队列尾节点的后一位
private int[] data; //数据
//初始化环形队列数据
public CircleArrayQueue(int maxSize) {
this.maxSize = maxSize;
this.data = new int[this.maxSize];
//this.rear = 0;
//this.front = 0;
}
//判断队列是否已满
public boolean isFull(){
if((rear + 1) % maxSize == front) {
return true;
}
return false;
}
//判断队列是否为空
public boolean isEmpty(){
if(rear == front) {
return true;
}
return false;
}
//添加数据
public void addQueue(int in){
if(isFull()) {
System.out.println("当前队列已满,无法添加数据");
return;
}
data[rear] = in;
rear = (rear+1) % maxSize;
}
//取出数据
public int popQueue(){
if(isEmpty()) {
throw new RuntimeException("当前队列为空,无法获取数据");
}
int value = data[front];
front = (front + 1) % maxSize;
return value;
}
//显示队列的有效数据
public void listQueue(){
if(isEmpty()) {
System.out.println("当前队列为空,无法获取数据");
return;
}
for(int i = front; i < front + dataLen(); i++) {
System.out.printf("data[%d] = %d\n", i % maxSize, data[i % maxSize]);
}
}
//获取队列的有效数据长度
public int dataLen() {
return (rear + maxSize - front) % maxSize;
}
//获取队列的首元素
public int head(){
if(isEmpty()) {
throw new RuntimeException("当前队列为空,无法获取数据");
}
return data[front];
}
}
在main方法中测试
public class CircleArrayQueueDemo{
public static void main(String[] args){
CircleArrayQueue queue = new CircleArrayQueue(4); //有效存储空间:3
queue.addQueue(1);
queue.addQueue(2);
queue.addQueue(3);
queue.addQueue(4);
queue.listQueue();
System.out.println("当前队列的长度:" + queue.dataLen());
System.out.println("-----------------------------------");
System.out.println(queue.popQueue());
System.out.println(queue.popQueue());
System.out.println(queue.popQueue());
System.out.println(queue.popQueue());
System.out.println(queue.popQueue());
}
}
测试结果
链队列
定义队列中的节点
class Node {
private String data;
private Node next; //指向下一个节点
public Node(String data) {
this.data = data;
}
public Node() {
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
public Node getNext() {
return next;
}
public void setNext(Node next) {
this.next = next;
}
}
定义一个 LinkedQueue 类,一个 LinkedQueue 对象就是一个链队列;同时在该栈中定义基本操作方法
class LinkedQueue {
//front变量,不存储数据,其next指向队列中的第一个节点
private Node front = new Node();
//rear变量,指向队列中的最后一个节点,默认和front指向同一个对象,表示当前队列为空
private Node rear = front;
//获取front
public Node getFront() {
return front;
}
//获取rear
public Node getRear() {
return rear;
}
//判断队列是否为空
public boolean isFull() {
return this.front.getNext() == null;
}
//入队列
public void enQueue(String data) {
Node node = new Node(data);
if (front.getNext() == null) { //如果添加的是第一个元素,则需要将 front的next指向该节点
this.front.setNext(node);
}
this.rear.setNext(node);
this.rear = node;
}
//出队列
public Node outQueue() {
//判断栈是否为空
if (isFull()) {
throw new RuntimeException("当前队列为空");
}
Node temp = this.front.getNext(); //用于临时存储要出队列的元素
//让front的next指向要出队列的元素(temp)的下一个元素
this.front.setNext(temp.getNext());
return temp;
}
//遍历队列
public void list() {
if (isFull()) {
throw new RuntimeException("当前队列为空");
}
Node temp = this.getFront().getNext();//辅助变量,接收front指向的第一个节点
while (temp != null) {
System.out.println(temp.getData());
temp = temp.getNext(); //temp后移
}
}
}
在main方法中测试
public class LinkedQueueDemo {
public static void main(String[] args) {
LinkedQueue queue = new LinkedQueue();
queue.enQueue("张三");
queue.enQueue("李四");
queue.enQueue("王五");
queue.list();
System.out.println("-----------------------");
System.out.println(queue.outQueue().getData());
System.out.println(queue.outQueue().getData());
System.out.println(queue.outQueue().getData());
System.out.println(queue.outQueue().getData());
}
}
测试结果