队列(二)-------循环队列

刚前一篇( 点击打开链接)也说到顺序队列存储时的问题,所以引出循环队列的解决方案。
      因为前一篇也说到了队列的基本概念,所以这里使用图示和代码直接理解。

图示(制作简陋,请见谅):
此时可以看出来rear当满了之后,就转头从0开始,继续往后。但是此时如何判断它是满的状态?只根据rear == front有局限性。这里我是加了一个判断front处的数据元素值是不是等于null.
判断队列的长度:rear > front, 则len = rear - front。2.rear < front , 则len = size - (front -  rear)。这里size是数组的大小。
此时是将它分为两端的0 - rear段 和 front - size。


参考代码:
public class LoopQueue<T> {
	
		private int DEFAULT_SIZE = 20;
		//记录数组的长度或者说容量
		private int length;
		//定义一个数组来存储这个队列的元素
		private Object[] elementData;
		//保存当前队列的个数
		private int front = 0;
		private int rear = 0;
		
		//根据默认的长度构建一个顺序队列
		public LoopQueue(){
			this.length = DEFAULT_SIZE;
			elementData = new Object[length];
		}
		
		//以一个初始元素建立顺序队列
		public LoopQueue(T data){
			this();
			elementData[0] = data;
			rear ++;
		}
		
		//以一个初始元素和指定的长度建立顺序队列   data相当于指定的第一个元素, initSize 指定顺序队列底层数组的长度
		public LoopQueue(T data, int initSize){
			this.length = initSize;
			elementData = new Object[length];
			elementData[0] = data;
			rear ++;
		}

		//插入队列
		public void insert(T data){
			if(rear == front && elementData[front] != null){//对于循环队列 空和满均有rear == front
				throw new IndexOutOfBoundsException("队列已满!");
			}
			elementData[rear++] = data;
			//如果插满了rear要再次等于0
			rear = rear == length ? 0 : rear;
		}
		
		//移除或者删除队列
		public T remove(){
			if(empty()){
				throw new IndexOutOfBoundsException("空队列!");
			}
			//队列front端的元素值
			T oldValue = (T)elementData[front];
			//释放队列front端的元素
			elementData[front++] = null;
			//如果front到头了, 那就需要转头
			front = front == length ? 0 : front;
			return oldValue;
		}
		
		//判断是否为空队列
		private boolean empty() {
			
			return rear == front && elementData[rear] == null;
		}
		
		//循环获取队列大小
		public int length(){
			if(empty()){
				return 0;
			}
			return rear > front ? rear - front : length - (front - rear);
		}
		
		//返回队头的元素
		public T element(){
			if(empty()){
				throw new IndexOutOfBoundsException("空队列!");
			}
			return (T)elementData[front];
		}
		
		//清空队列
		public void clear(){
			//将底层的数组所有元素赋值为Null
			Arrays.fill(elementData, null);
			front = 0;
			rear = 0;
		}
		
		public String toString(){
			if(empty()){
				return "[]";
			}
			else{
				if(front < rear){
					StringBuffer sb = new StringBuffer("[");
					for(int i = front ; i < rear ; i ++){
						sb.append(elementData[i].toString() + ", ");
					}
					int len = sb.length();
					return sb.delete(len - 2, len).append("]").toString();
				}
				else{
					StringBuffer sb = new StringBuffer("[");
					for(int i = front ; i < length ; i ++){
						sb.append(elementData[i].toString() + ", ");
					}
					for(int i = 0 ; i < rear ; i ++){
						sb.append(elementData[i].toString() + ", ");
					}
					int len = sb.length();
					return sb.delete(len - 2, len).append("]").toString();
				}
				}
	}

}

这里大部分的思路和顺序队列相近,可以参照代码及注释,图示去推理。

测试部分及截图:
public static void main(String[] args) {
		LoopQueue<String> lq = new LoopQueue<String>("aa", 4);
		lq.insert("bb");
		lq.insert("cc");
		lq.insert("dd");
		System.out.println(lq);
		lq.remove();
		System.out.println("此时的长度:" + lq.length());
		
		lq.insert("ee");
		System.out.println(lq);
		System.out.println("此时的长度:" + lq.length());
	}


参考:《疯狂java 突破程序员基本功的16课》


以上是这篇的大致内容,若有错误或需要改进的地方,请指教。谢谢!


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值