队列定义
栈(queue)是一种先进先出(first in first out,缩写为FIFO)的线性表。
它只允许在表的一端进行插入,而在另一端删除元素。
在队列中,允许插入的一端叫队尾(rear),允许删除的一端称为队头(front)。
队的属性与方法
Java程序代码实现
public interface IMyQueue<T> {
/*
* 入队
*/
boolean add(T data);
/*
* 出队
*/
T poll();
/*
* 查看队列的第一个元素,不出队
*/
T peek();
/*
* 队列长
*/
int length();
/*
* 队列是否为空
*/
boolean isEmpty();
/*
* 清空队列
*/
void clear();
}
队列的顺序表示
定义
队列的顺序表示是用一组地址连续的存储单元依次存放队列中的各个元素,并用指针front指向队头,指针rear指向队尾。
代码
Java程序代码实现
import java.util.Arrays;
public class MyArrayQueue<T> implements IMyQueue<T> {
private Object[] objs = new Object[16];
/*
* 队列长度
*/
private int size;
@Override
public boolean add(T data) {
if(size >= objs.length){
addLength();
}
objs[size++]=data;
return true;
}
@SuppressWarnings("unchecked")
@Override
public T poll() {
if(size==0){
return null;
}
Object temp = objs[0];
for(int i=0 ;i<size-1;i++){
objs[i] = objs[i+1];
}
size--;
return (T) temp;
}
@Override
public int length() {
return size;
}
@Override
public boolean isEmpty() {
return size == 0;
}
@Override
public void clear() {
for (int i = 0; i < size; i++) {
objs[i] = null;
}
size=0;
}
/*
* 增加数组长度
*/
private void addLength() {
objs = Arrays.copyOf(objs, size*3/2+1);
}
@Override
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append("MyArrayQueue:[");
for (int i = 0; i < size; i++) {
sb.append(objs[i]);
if(i != size-1){
sb.append(",");
}
}
sb.append("]");
return sb.toString();
}
@Override
public T peek() {
if(size==0){
return null;
}
return (T) objs[0];
}
}
队列的链式表示
定义
用链表表示的队列简称链队列。
一个链队列需要两个分别指示队头和队尾的指针(分别称为头指针和尾指针)才能唯一确定。
空的链队列的判决条件为头指针和尾指针均指向头节点。
代码
java程序代码实现
public class MyLinkedQueue<T> implements IMyQueue<T> {
/*
* 队首指针
*/
Node<T> front;
/*
* 队尾指针
*/
Node<T> rear;
/*
* 队列长度
*/
private int size;
/*
* 重载函数
*/
public MyLinkedQueue() {
Node<T> node = new Node<T>(null);
this.rear = node;
this.front = this.rear;
this.size = 0;
}
@Override
public boolean add(T data) {
Node<T> node = new Node<T>(data);
rear.next = node;
rear = node;
size++;
return true;
}
@Override
public T poll() {
if(size==0){
return null;
}
Object temp = front.next.data;
front = front.next;
size--;
return (T) temp;
}
@Override
public int length() {
return size;
}
@Override
public boolean isEmpty() {
return size == 0;
}
@Override
public void clear() {
rear = front=null;
size=0;
}
@Override
public T peek() {
return front.next.data;
}
}
循环队列
定义
和顺序栈相类似,在队列的顺序存储结构中,除了用一组地址连续的存储单元依次存放从队头到队尾的元素之外,需附设两个指针front和rear分别指示队列头元素及队列尾元素的位置。
在非空队列中,头指针始终指向队列头元素,而尾指针始终指向队列尾元素的下一个位置。只凭Q.front \== Q.rear无法判别队列空间是“空”还是“满”。可有两种处理方法:其一是另设一个标志位以区别队列是“空”还是“满”;其二是少用一个元素空间,约定以“队列头指针在队列尾指针的下一位置(指环状的下一位置)上”作为队列呈“满”状态的标志。
循环队列空或满的判断条件
队空:Q.front \== Q.rear
队满:Q.front \== (Q.rear+1)%MAXSIZE
代码
Java程序代码实现
public class CirularQueue<T> implements IMyQueue<T> {
/*
* 队首下标
*/
int front;
/*
* 队尾下标
*/
int rear;
private Object[] objs;
public CirularQueue(){
this(11); // 默认队列内有10个元素
}
public CirularQueue(int size) {
// 队列最大长度为size个元素,保证rear转一圈之后不会和head相等
// 也就是队列满的时候,rear+1=head,中间刚好空一个元素。当rear=head的时候,一定是队列空了
objs = new Object[size+1];
front = 0;
rear = 0;
}
/*
* 队列长度
*/
private int size;
@Override
public boolean add(T data) {
if(front == (rear+1)% (objs.length)){
return false;
}
objs[rear] = data;
rear = (rear+1)%(objs.length);
size++;
return true;
}
@Override
public T poll() {
if(front == rear){
return null;
}
Object temp = objs[front];
front = (front+1) % (objs.length);
size--;
return (T) temp;
}
@Override
public T peek() {
if(front == rear){
return null;
}
return (T) objs[front];
}
@Override
public int length() {
return size;
}
@Override
public boolean isEmpty() {
return size == 0;
}
@Override
public void clear() {
for(int i = front; i < front+size; i++){
objs[i%(objs.length)]=null;
}
front = rear = 0;
size = 0;
}
}