java语言队列实现_java语言实现队列

什么是队列:

队列(queue)是只允许在一端进行插入操作,而在另一端进行删除操作的线性表。队列是一种先进先出(First In First Out)的线性表,简称FIFO。允许插入的一端称为队尾,允许删除的一端称为队头。

队列的基本操作:

enqueue(Object obj):入队操作

dequeue():出队操作

循环队列:

由于队列如果做成数组的形式,为了保证出队列的时间复杂度为O(1),所以不能将数组中的元素进行移动(如果移动,时间复杂度就变为了O(n))。因此前面出栈之后的元素空间就会被浪费。所以我们将数组的头尾进行相接,这样就形成了循环,我们称这样的队列为循环队列。结构图如下所示:

0818b9ca8b590ca3270a3433284dd417.png

判断队列为空:front指针指向队头元素,rear指针指向队尾元素的下一个位置,这样的front等于rear的时候,此时队列不是还剩下一个元素,而是为空队列。所以空队列的判断为front == rear。

判断队列为满:当队列为满时,我们修改其条件,保存一个元素空间。也就是说,队列为满时,数组中还有一个空闲单元。(这就是为什么后面的代码中数组的大小为5,却最多可以插入4个元素)所以满队列的判断为(rear+1)%QueueSize == front。 代码示例如下:

package queue;

/**

* 数组中只存储数组大小-1个元素,

* 保证rear转一圈之后不会和head相等,

* 也就是队列满的时候,rear+1=head,

* 中间刚好空一个元素。

* 当rear=head的时候,一定是队列空了。

*

*/

public class QueueArray {

private Object[] objs;

private int front;

private int rear;

public QueueArray(){

this(10);

}

public QueueArray(int size){

objs = new Object[size];

front = 0;

rear = 0;

}

public boolean enqueue(Object obj){

//判断队列是否为满

if((rear+1)%objs.length == front){

return false;

}

objs[rear] = obj;

rear = (rear+1)%objs.length;

return true;

}

public Object dequeue(){

//判断队列是否为空

if(rear == front){

return null;

}

Object obj = objs[front];

front = (front+1)%objs.length;

return obj;

}

public void traverse(){

while(front != rear){

System.out.print(objs[front]+" ");

front = ((front+1)%objs.length);

}

}

public static void main(String[] args) {

QueueArray q = new QueueArray(5);

q.enqueue("A");

q.enqueue("B");

q.enqueue("C");

System.out.println("删除的元素为:"+q.dequeue());

q.enqueue("F");

System.out.println("删除的元素为:"+q.dequeue());

q.traverse();

}

}

队列的链式存储方式:

入队与出队结构图:

0818b9ca8b590ca3270a3433284dd417.png              

0818b9ca8b590ca3270a3433284dd417.png

入队:将新节点作为原来节点的后继,再将新节点设置为尾节点。this.rear.next = newNode;    this.rear = newNode;

出队:将需要删除节点的后继直接赋值给头结点的后继即可。this.front.next = node.next;

具体代码示例如下:

package queue;

public class LinkQueue {

private class Node{

private T data;

private Node next;

public Node(){}

}

private Node front;

private Node rear;

private int count;//队列中元素的数量

public LinkQueue(){

Node p = new Node();

p.data = null;

p.next = null;

front = rear = p;

}

//使用尾插法插入数据

public void equeue(T item){

Node newNode = new Node();

newNode.data = item;

newNode.next = null;

this.rear.next = newNode;

this.rear = newNode;

count++;

}

public T dequeue() throws Exception{

if(isEmpty()){

throw new Exception("队列为空!");

}

T obj;

Node node = this.front.next;

obj = node.data;

this.front.next = node.next;

if(rear == node){

rear = front;

}

count --;

return obj;

}

public int size(){

return count;

}

public boolean isEmpty(){

return front == rear;

}

public void traverse(){

Node current = front.next;

while(current != null){

System.out.println(current.data);

current = current.next;

}

}

public static void main(String[] args) throws Exception {

LinkQueue lq = new LinkQueue();

lq.equeue("A");

lq.equeue("B");

lq.equeue("C");

lq.equeue("D");

lq.traverse();

System.out.println("队列的长度为:"+lq.size());

System.out.println("删除的元素为:"+lq.dequeue());

lq.traverse();

}

}无论是循环队列还是链式队列,从时间上看基本都是常数的时间,即时间复杂度都为O(1)。不过循环队列是事先申请好了空间,使用期间不释放。而对于链式队列,每次申请或释放节点也会存在一定的开销,如果入队或出队频繁,则还是存在细微的差异,但是链式队列在空间上更加灵活。所以,在可以确定队列长度最大值的情况下,建议用循环队列,如果无法预估队列的长度,则使用链队列。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值