#数据结构--基于数组实现双端队列

4.8.4.6 源码

package com.yzh.maven.entity;

import java.util.ConcurrentModificationException;
import java.util.EmptyStackException;
import com.yzh.maven.base.abstracts.MyQueueAbstract;
import com.yzh.maven.base.dao.MyDequeDao;
import com.yzh.maven.base.dao.MyIterator;
import com.yzh.maven.utils.MyArraysUtils;

/**
 * @className MyFrontTailArrayDeque<E>
 * @description 基于数组实现双端队列
 * @author yzh
 * @date 2019-04-21
 * @param <E>
 */
public class MyFrontTailArrayDeque<E> extends MyQueueAbstract<E> implements MyDequeDao<E>{
	
	/**循环数组*/
	private Object[] loopArray = {}; 
	/**队列大小*/
	private int size;
	/**循环数组初始化容量*/
	private static final int INIT_CAPACITY = 16;
	/**队列头指针*/
	private int front;
	/**队列尾指针*/
	private int tail;
	private int modCount;
	
	public MyFrontTailArrayDeque(){
		//初始化数组
		loopArray = new Object[INIT_CAPACITY];
	}
	
	/***
	 * @functionName:size
	 * @description:队列的大小
	 * @author yzh
	 * @date 2019-04-13
	 * @return int
	 */
	@Override
	public int size(){
		return size;
	}
	
	/queue
	/***
	 * @functionName:add
	 * @description:实现元素的添加。
	 * @param e
	 * @author yzh
	 * @date 2019-04-13
	 * @return boolean
	 */
	public boolean add(E e) {
		this.addLast(e);
		return true;
	}
	/***
	 * @functionName:offer
	 * @description:用于实现元素的添加。入队成功返回true,否则返回false,即如果队列已满直接返回false,队列未满则直接插入并返回true。
	 * @param e
	 * @author yzh
	 * @date 2019-04-13
	 * @return boolean
	 */
	public boolean offer(E e) {
		return this.offerLast(e);
	}
	
	/***
	 * @functionName:remove
	 * @description:方法直接删除队头的元素。
	 * @author yzh
	 * @date 2019-04-13
	 * @return E
	 */
	public E remove() {
		return this.removeLast();
	}
	
	/***
	 * @functionName:poll
	 * @description:方法取出并删除队头的元素,当队列为空,返回null。
	 * @author yzh
	 * @date 2019-04-13
	 * @return E
	 */
	public E poll() {
		return this.pollLast();
	}
	
	/***
	 * @functionName:peek
	 * @description:方法直接取出队头的元素,并不删除。
	 * @author yzh
	 * @date 2019-04-13
	 * @return E
	 */
	public E peek() {
		return this.getFirst();
	}	
	
	/***
	 * @functionName:isEmpty
	 * @description:判断队列是否为空
	 * @author yzh
	 * @date 2019-04-13
	 * @return boolean
	 */
	public boolean isEmpty(){
		return size == 0;
	}
	
	///deque/
	/***
	 * @functionName:addFirst
	 * @description:从对头添加元素
	 * @author yzh
	 * @date 2019-04-20
	 * @return
	 */
	
	public void addFirst(E e) {
	    if (e == null){
	        throw new NullPointerException();
	    }
	    //循环数组长度
	    int loopArrayLen = loopArray.length;
	    //队列头指针从数组末尾向左移动指针
	    front = (front - 1 + loopArrayLen) % loopArrayLen;
	    //添加元素
	    loopArray[front] = e;
	    //当头指针与与尾指针重合时作为扩容的条件
	    if(front == tail){
	    	expectedCapacity(loopArrayLen);
	    }
		modCount++;
		size++;
	}
	
	/***
	 * @functionName:expectedCapacity
	 * @description:循环数组扩容
	 * @param capacity 数组的当前容量
	 * @author yzh
	 * @date 2019-04-20
	 * @return
	 */
	private void expectedCapacity(int capacity) {
		//队列头
		int start = front;
		//原数组容量
		int oldCapacity = capacity;
		//扩容后的容量
		int newCapacity = oldCapacity << 1;
		Object[] newLoopArray = new Object[newCapacity];
		//拷贝front到array.length -1区间的元素
		MyArraysUtils.arrayCopy(loopArray, start, newLoopArray, 0, oldCapacity - start);
		//拷贝0到tail区间的元素
		MyArraysUtils.arrayCopy(loopArray, 0, newLoopArray, oldCapacity - start, start);
		loopArray = newLoopArray;
		//扩容后队头指针起始值
		front = 0;
		//扩容后队尾指针起始值
		tail = oldCapacity;
	}

	/***
	 * @functionName:addLast
	 * @description:从对尾添加元素
	 * @author yzh
	 * @date 2019-04-20
	 * @return
	 */
	public void addLast(E e) {
	    if (e == null){
	        throw new NullPointerException();
	    }
	    //循环数组长度
	    int loopArrayLen = loopArray.length;
	    loopArray[tail] = e;
	    tail = (tail + 1) % loopArrayLen;
	    //扩容
	    if(front == tail){
	    	expectedCapacity(loopArrayLen);
	    }
		modCount++;
		size++;
	}

	/***
	 * @functionName:offerFirst
	 * @description:从队列的开头实现元素的添加。入队成功返回true
	 * @author yzh
	 * @date 2019-04-20
	 * @return
	 */
	@Override
	public boolean offerFirst(E e) {
		addFirst(e);
		return true;
	}

	/***
	 * @functionName:offerLast
	 * @description:从队列的末尾实现元素的添加。入队成功返回true
	 * @author yzh
	 * @date 2019-04-20
	 * @return
	 */
	@Override
	public boolean offerLast(E e) {
		addLast(e);
		return false;
	}

	/***
	 * @functionName:removeFirst
	 * @description:从队头实现元素的删除
	 * @author yzh
	 * @date 2019-04-20
	 * @return
	 */
	@Override
	public E removeFirst() {
		//方法取出并删除队头的元素,当队列为空,返回null。
		E e = pollFirst();
		//如果元素为空,那么抛出空指针异常
		if(e == null){
			 throw new NullPointerException();
		}
		return e;
	}

	/***
	 * @functionName:removeLast
	 * @description:从队尾实现元素的删除
	 * @author yzh
	 * @date 2019-04-20
	 * @return
	 */
	@Override
	public E removeLast() {
		//方法取出并删除队尾的元素,当队列为空,返回null。
		E e = pollLast();
		//如果元素为空,那么抛出空指针异常
		if(e == null){
			 throw new NullPointerException();
		}
		return e;
	}

	/***
	 * @functionName:pollFirst
	 * @description:取出并删除队头的元素,当队列为空,返回null
	 * @author yzh
	 * @date 2019-04-20
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public E pollFirst() {
		//如果队列为空,那么返回null
		if(isEmpty()){
			return null;
		}
		//获取队头元素
		E e = (E)loopArray[front];
		//置空(删除)队头元素
		loopArray[front] = null;
		//队头指针向右移动一个位置
		int newFront = (front + 1) % loopArray.length;
		front = newFront;
		modCount++;
		size--;
		return e;
	}
	
	/***
	 * @functionName:pollLast
	 * @description:取出并删除队尾的元素,当队列为空,返回null
	 * @author yzh
	 * @date 2019-04-20
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public E pollLast() {
		//如果队列为空,那么返回null
		if(isEmpty()){
			return null;
		}
		//获取队尾元素的索引
		tail = getEndEIndexByTail();
		//由于尾指针总是在队尾元素的下一个索引位置上(或者位于loopArray.length - 1索引位置上),因此总是需要先把尾指针移动到最后一个元素的索引位置上,然后再获取即将删除的队尾元素
		E e = (E)loopArray[tail];
		//置空(删除)队尾元素
		loopArray[tail] = null;
		modCount++;
		size--;
		return e;
	}

	/***
	 * @functionName:getFirst
	 * @description:取出但不删除队头的元素,当队列为空,抛出异常
	 * @author yzh
	 * @date 2019-04-20
	 * @return
	 */
	@SuppressWarnings("unchecked")
	@Override
	public E getFirst() {
		//如果队列为空,那么抛出异常
		if(isEmpty()){
			throw new RuntimeException("this dueue is null!");
		}
		return (E)loopArray[front];
	}
	
	/***
	 * @functionName:getLast
	 * @description:取出但不删除队尾的元素,当队列为空,抛出异常
	 * @author yzh
	 * @date 2019-04-20
	 * @return
	 */
	@Override
	public E getLast() {
		//如果队列为空,那么抛出异常
		if(isEmpty()){
			throw new RuntimeException("this dueue is null!");
		}
		//获取队尾元素的索引
		int tailEIndex = getEndEIndexByTail();
		@SuppressWarnings("unchecked")
		E e = (E)loopArray[tailEIndex];
		return e;
	}

	/***
	 * @functionName:getEndEIndexByTail
	 * @description:通过tail指针获取队尾元素的索引
	 * @author yzh
	 * @date 2019-04-20
	 * @return
	 */
	private int getEndEIndexByTail() {
		int tailEIndex = 0;
		int temp = tail;
		//如果tail尾指针的索引>0,那么需要将尾指针向左移动一个位置,以便等于元素队尾元素的索引
		if(temp > 0){
			tailEIndex = (temp - 1) % loopArray.length;
		//如果未调用过addLast方法,说明tail = 0,那么就需要将队尾元素的索引为初始化数组的尾部索引位置
		//如果未调用过addLast方法,说明tail = 0,那么就需要将尾指针移动到初始化数组的尾部索引位置,此时由于不能将指针移动到值为loopArray.length的索引位置上,所以这里的tail指针无需向左移动一个位置
		}else{
			tailEIndex = loopArray.length - 1;
		}
		return tailEIndex;
	}

	/***
	 * @functionName:peekFirst
	 * @description:取出队头的元素,并不删除
	 * @author yzh
	 * @date 2019-04-20
	 * @return
	 */
	@SuppressWarnings("unchecked")
	@Override
	public E peekFirst() {
		return (E)loopArray[front];
	}
	
	/***
	 * @functionName:peekLast
	 * @description:取出队尾的元素,并不删除
	 * @author yzh
	 * @date 2019-04-20
	 * @return
	 */
	@SuppressWarnings("unchecked")
	@Override
	public E peekLast() {
		//获取队尾元素的索引
		int tailEIndex = getEndEIndexByTail();
		E e = (E)loopArray[tailEIndex];
		return (E) e;
	}

	///Stack///
	/***
	 * @functionName:push
	 * @description:入栈操作
	 * @author yzh
	 * @date 2019-04-20
	 * @return
	 */
	@Override
	public void push(E e) {
		this.addLast(e);
	}
	
	/***
	 * @functionName:pop
	 * @description:出栈操作
	 * @author yzh
	 * @date 2019-04-20
	 * @return E
	 */
	@Override
	public E pop() {
		//如果栈空则抛出异常
	    if (isEmpty()){
	    	throw new EmptyStackException();
	    }
		E e = this.pollLast();
		return e;
	}

	///collection//
	/***
	 * @functionName:remove
	 * @description:删除集合元素
	 * @param o 目标元素
	 * @author yzh
	 * @date 2019-04-20
	 * @return boolean
	 */
	@SuppressWarnings("unchecked")
	@Override
	public boolean remove(Object o) {
		if(isEmpty()){
			return false;
		}
		int loopEIndex = 0;
		E e = null;
		for(int i = front;i<size();i++){
			loopEIndex = i % loopArray.length;
			e = (E) loopArray[loopEIndex];
			if(e == null && o == null){
				this.delete(loopEIndex);
				return true;
			}else if(e != null && o != null && o.equals(e)){
				
				this.delete(loopEIndex);
				return true;
			}else{
				loopEIndex++;
				continue;
			}
		}
		modCount++;
		return false;
	}
	
	/*	
	 	private E get(int index){
		if(!(0 <= index && index < size)){
			throw new RuntimeException("this index is illagel!");
		}
		return (E) loopArray[index];
	}*/
	
	private void delete(int index){
		if(!(0 <= index && index < size)){
			throw new RuntimeException("this index is illagel!");
		}
		MyArraysUtils.arrayCopy(loopArray, index + 1, loopArray, index, size() - (index + 1));
		//尾指针tail同步移动位置
		tail = getEndEIndexByTail();
		//置空尾指针的元素
		loopArray[tail] = null;
		modCount++;
		size--;
	}
	
	
	/***
	 * @functionName:contains
	 * @description:判断元素是否在集合中
	 * @param o 目标元素
	 * @author yzh
	 * @date 2019-04-20
	 * @return boolean
	 */
	@SuppressWarnings("unchecked")
	@Override
	public boolean contains(Object o) {
		if(!isEmpty()){
			int loopEIndex = 0;
			E e = null;
			for(int i = front;i<size();i++){
				loopEIndex = i % loopArray.length;
				e = (E) loopArray[loopEIndex];
				if(e == null && o == null){
					return true;
				}else if(e != null && o != null && o.equals(e)){
					return true;
				}else{
					loopEIndex++;
					continue;
				}
			}
		}
		return false;
	}
	
	/***
	 * @functionName:iterator
	 * @description:创建迭代器
	 * @author yzh
	 * @date 2019-04-13
	 */
	public MyIterator<E> iterator() {
		return new MyItr();
	}
	
	
	/**
	 * @className MyItr
	 * @description 迭代器
	 * @author yzh
	 * @date 2019-04-21
	 */
	private class MyItr implements MyIterator<E>{
		//当亲索引
		private int curIndex;
		//元素游标,可以移动到下一个元素
		private int cursor = front;
		//用于判断是否使用了迭代的删除方法并初始化为modCount
		private int expectedMoCount = modCount;
		
		/**
		 * @functionName hasNext
		 * @description 判断迭代器是否还有元素怒
		 * @author yzh
		 * @date 2018-12-31
		 * @param <E>
		 */
		@Override 
		public boolean hasNext() {
			//当游标(front指针)与tail指针重合时,此时表示队列为空
			return cursor != tail;
		}
	
		/**
		 * @functionName next
		 * @description 获取下一个元素
		 * @author yzh
		 * @date 2018-12-31
		 * @param <T>
		 */
		@SuppressWarnings("unchecked")
		@Override
		public E next() {
			//1.检查是否使用了迭代器的remove方法,且不能在迭代器中使用外部的add方法
			checkUseIteratorFlag();
			//2.记录当前元素的索引
			cursor = cursor % loopArray.length;
			curIndex = cursor;
			//3.返回当前元素,且游标移动到下一个元素
			return (E) loopArray[cursor++];
		}
	
		/**
		 * @functionName remove
		 * @description 删除当前元素
		 * @author yzh
		 * @date 2019-04-21
		 * @param <T>
		 */
		@Override
		public void remove() {
			//1.检查是否使用了迭代器的remove方法,且不能在迭代器中使用当前list外部的add方法
			checkUseIteratorFlag();
			//2.删除元素,此时size-1,所以第3步应把cursor-1,因为删除的后一个元素的索引会向前移动一个位置
			delete(curIndex);
			//3.重新为游标设值,游标回移
			cursor = curIndex;
			//4.由于调用了remove方法,所以modCount改变了,所以要把expectedMoCount重新赋值
			expectedMoCount = modCount;
		}
		
		/**
		 * @functionName checkUseIteratorFlag
		 * @description 检查是否使用了迭代器的删除方法
		 * @author yzh
		 * @date 2019-04-21
		 * @param <E>
		 */
		private void checkUseIteratorFlag(){
			if(modCount != expectedMoCount){
				throw new ConcurrentModificationException();
			}
		}
	}
	
	/***
	 * @functionName:toString
	 * @description:重写toString方法
	 * @author yzh
	 * @date 2019-04-13
	 * @return String
	 */
	@Override
	public String toString(){
		MyIterator<E> it = this.iterator();
		if(isEmpty()){
			return "[]";
		}
		StringBuffer sbf = new StringBuffer();
		sbf.append("[");
		E e = null;
		for(;;){
			e = it.next();
			if(!it.hasNext()){
				return sbf.append(e).append("]").toString();
			}
			sbf.append(e).append(",");
		}
	}
	
	/***
	 * @functionName:toString
	 * @description:重写toString方法
	 * @author yzh
	 * @date 2019-04-13
	 * @return String
	
	@Override
	public String toString(){
		if(isEmpty()){
			return "[]";
		}
		int temp = front;
		StringBuffer sbf = new StringBuffer();
		sbf.append("[");
		for(int i = 0;i<size();i++){
			sbf.append(loopArray[temp % loopArray.length]);
			if(i < size() - 1){
				sbf.append(",");
			}
			temp++;
		}
		sbf.append("]");
		return sbf.toString();
	}*/
}

注意:在实际应用中,我们不太可能在两端任意插入元素并在两端取出这些元素,因此,双端队列不如简单队列那样常用。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值