队列

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;
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值