1、队列
只允许在一端进行插入操作,而在另一端进行删除操作的线性表。
(先进先出) 简称FIFO。队尾插入,队头删除。
入队:在队尾追加元素,不需要移动任何元素,时间复杂度为O(1)。
出队:队列元素的出列在队头,即下标为0的位置,意味着队列中的所有元素都要向前移动,以保证队列的队头,也就是下标为0的位置不为空,时间复杂度为O(n)。(队头不需要一定在下标为0的位置)
为了避免当只有一个元素时,队头和队尾重合使处理变得麻烦,所以引入两个指针,front指针指向队头元素,rear指针指向队尾元素的下一个位置,这样当front等于rear时,此队列不是还剩一个元素,而是空队列。
2、循环队列
队列的头尾相接的顺序存储结构。
由于rear可能比front大,也可能比front小,所以尽管它们只相差一个位置时就是满的情况,但也可能是相差整整一圈。所以若队列的最大尺寸为QueueSize,那么队列满的条件时(rear+1)%QueueSize==front(取模“%”的目的就是为了整合rear与front大小为一个问题)。
计算队列长度公式为:(rear-front+QueueSize)%QueueSize
循环队列的顺序存储结构代码如下:
typedef int QElemType; /*QWlemType类型根据实际情况而定,这里假设为int */
/*循环队列的顺序存储结构*/
typedef struct
{
QElemType data[MAXSIZE];
int front; /*头指针*/
int rear; /*尾指针,若队列不空,指向队列尾元素的下一个位置*/
}SqQueue;
循环队列的初始化代码如下:
/*初始化一个空队列Q*/
Status InitQueue(SqQueue *Q)
{
Q->front=0;
Q->rear=0;
return OK;
}
循环队列求队列长度代码如下:
/*返回Q的元素个数,也就是队列的当前长度*/
int QueueLength(SqQueue Q)
{
return (Q.rear-Q.front+MAXSIZE)%MAXSIZE;
}
循环队列的入队操作代码如下:
/*若队列未满,则插入元素e为Q新的队尾元素*/
Status EnQueue(SqQueue *Q,QElemmType e)
{
if((Q->rear+1)%MAXSIZE==Q->front) /*队列满的判断*/
return ERROR;
Q->data[Q->rear]=e; /*将元素e赋值给队尾*/
Q->rear=(Q->rear+1)%MAXSIZE; /*rear指针向后移一个位置*/
/*若到最后则转到数组头部*/
return OK;
}
循环队列的出队操作代码如下:
/*若队列不空,则删除Q中队头元素,用e返回其值*/
Status DeQueue(SqQueue *Q,QElemType *e)
{
if(Q->front==Q->rear) /*队列空的判断*/
return ERROR;
*e=Q->data[Q->front]; /*将队头元素赋值给e*/
Q->front=(Q->front+1)%MAXSIZE; /*front指针向后移一个位置*/
/*若到最后则转到数组头部*/
return OK;
}
3、链队列
队头指针指向链队列的头结点,队尾指针指向终端结点。
空队列时,front和rear都指向头结点。
链队列的结构为:
typedef int QElemType; /*QElemType类型根据实际情况而定,这里假设为int*/
typedef struct QNode /*结点结构*/
{
QElemType data;
struct QNode *next;
}QNode,*QueuePtr;
typedef struct /*队列的链表结构*/
{
QueuePtr front,rear; /*队头、队尾指针*/
}LiinkQueue;
入队操作代码:
/*插入元素e为Q的新的队尾元素*/
Status EnQueue(LinkQueue *Q,QElemType e)
{
QueuePtr s=(QueuePtr)malloc(sizeoof(QNode));
if(!s) /*存储分配失败*/
exit(OVERFLOW);
s->data=e;
s->next=NULL;
Q->rear->next=s; /*把拥有元素e新结点s赋值给原队尾结点的后继*/
Q->rear=s; /*把当前的s设置为队尾结点,rear指向s*/
return Ok;
}
出队操作代码:
出队操作时,就是头结点的后继结点出队,将头结点的后继改为它后面的结点,若链表除头结点外只剩下一个元素时(出队后变为空链队),则需将rear指向头结点。
/*若队列不空,删除Q的队头元素,用e返回其值,并返回OK,否则返回ERROR*/
Status DeQueue(LinkQueue *Q,QElemType *e)
{
QueuePtr p;
if(Q->front==Q->rear)
{
retur ERROR;
}
p=Q->front->next; /*将欲删除的队头结点暂存给p*/
*e=p->data; /*将欲删除的队头结点的值赋给e*/
Q->front->next=p->next; /*将原队头结点后继p->next赋值给头结点后继*/
if(Q->rear==p) /*若队头是队尾,则删除后将rear指向头结点*/
{
Q->rear=Q->front;
}
free(p);
return Ok;
}
Java实现代码:
1、队操作:
public class Queue {
private static final int defaultSize=10;//默认大小
private int front; //队头指针
private int rear; //队尾指针
private int count; //元素个数
private int maxQueueSize; //最大元素个数
private Object[] queue; //对象数组
//带参数的构造参数,创建指定大小的队列空间
public Queue(int size) {
queue=new Object[size];
maxQueueSize=size;
front=rear=0;
}
//无参数的构造函数,创建默认大小的队列空间
public Queue() {
maxQueueSize=defaultSize;
count=0;
queue=new Object[defaultSize];
}
//入队列
public boolean push(Object obj) {
if (!isFull()) {
queue[rear]=obj;
rear=(rear+1)%maxQueueSize;
count++;
return true;
}else {
System.out.println("队列已满!"+obj+"无法插入队列");
return false;
}
}
//出队列
public Object pop() {
Object object=null;
if (!isEmpty()) {
object=queue[front];
front=(front+1)%maxQueueSize;
count--;
}else {
System.out.println("队列已空!");
}
return object;
}
public Object getHead() {
Object object=null;
if (!isEmpty()) {
object=queue[front];
}else {
System.out.println("队列已空!");
}
return object;
}
public int size() {
return count;
}
public boolean isEmpty() {
return count==0;
}
public boolean isFull() {
return (count>0)&&(rear==front);
}
public void clear() {
count=0;
front=rear=0;
}
2、测试
Queue queue=new Queue();
int[] a={1,2,3,4,5,6,7};
for (int i = 0; i < a.length; i++) {
queue.push(new Integer(a[i]));
}
System.out.println("输出队列大小:");
System.out.println(queue.size());
System.out.println("输出队列内容:");
while(!queue.isEmpty()){
System.out.println(queue.pop().toString());
}
package com.jredu.test;
public class Queue {
private Object[] arr = new Object[5];//用数组存放,大小为5
private int front = 0;
private int rear = 0;
public void push(Object val)
{
if (((front+1) % arr.length) == rear)
{
System.out.println("队列已满");
return;
}
arr[front] = val;
front++;
/*if (front == arr.length)
{
front = 0;
}*/
front %= arr.length;
}
public Object pop ()
{
if (front == rear)
{
return null;
}
Object val = arr[rear];
rear++;
rear %= arr.length;
return val;
}
}