DS04-循环队列

本文详细介绍了循环队列的实现原理,对比数组队列,循环队列能显著降低出队操作的时间复杂度,从O(n)降低到O(1),通过合理利用已出队元素的空间,避免了频繁的数据移动。文章还提供了具体的Java代码实现,包括队列的扩容和缩容策略。

循环队列相比于数组队列,最大的特点就是可以降低出队操作的时间复杂度,从O(n)将为O(1),降低移动的次数(不是完全不用移动),具体实现的原理就是队列在出队一个队首元素以后,队列中剩下的元素的相互间的顺序并没有改变,如果不想在每次出队操作之后把所有元素移动一次,那就得利用已经出队的那个元素原来占有的位置,这样就出现循环队列

循环队列底层还是用数组实现,可以定义一个int类型的front变量和一个tail变量,分别用于记录队头元素所在的索引值和下一个入队的元素应该插入的位置的索引值.所以,循环队列为空的条件就是front==tail,由于是循环队列,所以表示相对位置的许多操作使用模运算实现

实现的时候还是先设计一个Queue接口类,用于定义一些队列所必须拥有的操作,再定义一个LoopQueue类实现这个接口

具体代码如下:
Queue接口类:

public interface Queue<E> {
	public void enqueue(E e);
	public E dequeue();
	public E getFront();
	public int getSize();
	public boolean isEmpty();
}

LoopQueue循环队列类:

public class LoopQueue<E> implements Queue<E> {
	private E[] data;
	private int front,tail,size;
	
	public LoopQueue(int capacity) {
		data = (E[])new Object[capacity + 1];
		front = 0;
		tail = 0;
		size = 0;
	}
	
	public LoopQueue() {
		this(10);
	}
	
	@Override
	public boolean isEmpty() {
		return front == tail;
	}
	
	@Override
	public int getSize() {
		return this.size;
	}
	
	public int getCapacity() {
		return this.data.length - 1;
	}
	
	@Override
	public void enqueue(E e) {
		if( (tail + 1) % data.length == front) {
			reSize(getCapacity() * 2);
		}
		data[tail] = e;
		tail = (tail + 1) % data.length;
		size ++;
	}
	
	@Override
	public E dequeue() {
		if( isEmpty() ) {
			throw new IllegalArgumentException("队列为空");
		}
		E ret = data[front];
		data[front] = null;
		front = (front + 1) % data.length;
		size --;
		if( size == getCapacity() / 4 && getCapacity() / 2 != 0) {
			reSize(getCapacity() / 2);
		}
		return ret;
	}

	@Override
	public E getFront() {
		if( isEmpty() ) {
			throw new IllegalArgumentException("队列为空");
		}
		return data[front];
	}
	
	private void reSize(int capacity) {
		E[] newData = (E[])new Object[capacity];
		for(int i = 0; i < size; i++) {
			newData[i] = data[(front + i ) % data.length];
		}
		data = newData;
		front = 0;
		tail = size;
	}
	
	@Override
	public String toString() {
		StringBuilder sb = new StringBuilder("LoopQueue : size = "+getSize()+", capacity = "+getCapacity() +", length = "+ data.length + ", front [ ");
		for(int i = front; i != tail ;  i =(i + 1) % data.length) {
			sb.append(data[i]);
			if( (i + 1) % data.length != tail) {
				sb.append(", ");
			}
		}
		sb.append(" ] tail");
		return sb.toString();
	}
	
	public static void main(String[] args) {
		LoopQueue<Integer> queue = new LoopQueue<Integer>();
		for(int i = 0; i < 15; i++) {
			queue.enqueue(i);
			System.out.println(queue);
		}
		
		queue.dequeue();
		System.out.println(queue);
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值