自己动手实现java数据结构(四)双端队列
发布时间:2021-04-01 08:17:15 所属栏目:安全 来源:网络整理
导读:1.双端队列介绍 在介绍双端队列之前,我们需要先介绍队列的概念。和栈相对应,在许多算法设计中,需要一种" 先进先出(First Input First Output) "的数据结构,因而一种被称为" 队列(Queue) "的数据结构被抽象了出来(因为现实中的队列,就是先进先出的)。 队
|
在remove操作中有多种可能的情况,由于思路相通,可以通过上面的举例说明帮助理解。 /**
* 双端队列 迭代器实现
* private class Itr implements Iterator<E> {
* 当前迭代下标 = head
* 代表遍历从头部开始
* */
int currentIndex = ArrayDeque..head;
* 目标终点下标 = tail
* 代表遍历至尾部结束
* int targetIndex = ArrayDeque.
* 上一次返回的位置下标
* lastReturned;
@Override
hasNext() {
:::当前迭代下标未到达终点,还存在下一个元素
this.currentIndex != .targetIndex;
}
@Override
@SuppressWarnings("unchecked")
E next() {
:::先暂存需要返回的元素
E value = (E)ArrayDeque..currentIndex];
:::最近一次返回元素下标 = 当前迭代下标
this.lastReturned = .currentIndex;
:::当前迭代下标 向后移动一位(需要取模)
this.currentIndex = getMod(this.currentIndex + 1);
value;
}
@Override
remove() {
if(this.lastReturned == -1){
throw new IteratorStateErrorException("迭代器状态异常: 可能在一次迭代中进行了多次remove操作");
}
:::删除当前迭代下标的元素
boolean deleteFromTail = delete(.currentIndex);
:::如果从尾部进行收缩
if(deleteFromTail){
:::当前迭代下标前移一位
this.currentIndex - 1:::为了防止用户在一次迭代(next调用)中多次使用remove方法,将lastReturned设置为-1
this.lastReturned = -1;
}
* 删除队列内部数组特定下标处的元素
* @param currentIndex 指定的下标
* true 被删除的元素靠近尾部
* false 被删除的元素靠近头部
* boolean delete( currentIndex){
Object[] elements = ArrayDeque..elements;
int head = ArrayDeque..head;
int tail = ArrayDeque..tail;
:::当前下标 之前的元素个数
int beforeCount = getMod(currentIndex - head);
:::当前下标 之后的元素个数
int afterCount = getMod(tail - currentIndex);
:::判断哪一端的元素个数较少
if(beforeCount < afterCount){
:::距离头部元素较少,整体移动前半段元素
:::判断头部下标 是否小于 当前下标
if(head < currentIndex){
:::小于,正常状态 仅需要复制一批数据
:::将当前数组从"头部下标"开始,整体向右平移一位,移动的元素个数为"当前下标 之前的元素个数"
System.arraycopy(elements,head,elements,head+1,beforeCount);
}else{
:::不小于,说明存在溢出环 需要复制两批数据
:::将数组从"0下标处"的元素整体向右平移一位,移动的元素个数为"从0到当前下标之间的元素个数"
System.arraycopy(elements,1:::将数组最尾部的数据设置到头部,防止被覆盖
elements[0] = elements[(elements.length-1)];
:::将数组尾部的数据整体向右平移一位
System.arraycopy(elements,head+1,(elements.length-head-1));
}
:::释放被删除元素的引用
elements[currentIndex] = ;
:::头部下标 向右移动一位
ArrayDeque.this.head = getMod(ArrayDeque.);
:::没有删除尾部元素 返回false
false;
}{
:::距离尾部元素较少,整体移动后半段元素
:::判断尾部下标 是否小于 当前下标
if(currentIndex < tail){
:::将当前数组从"当前"开始,整体向左平移一位,移动的元素个数为"当前下标 之后的元素个数"
System.arraycopy(elements,currentIndex+1:::将数组从"当前下标处"的元素整体向左平移一位,移动的元素个数为"从当前下标到数组末尾的元素个数-1 ps:因为要去除掉被删除的元素"
System.arraycopy(elements,currentIndex+1,(elements.length-currentIndex-1));
:::将数组头部的元素设置到末尾
elements[elements.length-1] = elements[0];
:::将数组头部的数据整体向左平移一位,移动的元素个数为"从0到尾部下标之间的元素个数"
System.arraycopy(elements,1,0:::尾部下标 向左移动一位
ArrayDeque.this.tail = getMod(ArrayDeque.);
3.2?基于链表的链式双端队列和向量不同,双向链表在头尾部进行插入、删除操作时,不需要额外的操作,效率极高。 因此,我们可以使用之前已经封装好的的双向链表作为基础,轻松的实现一个链式结构的双端队列。限于篇幅,就不继续展开了,有兴趣的读者可以尝试自己完成这个任务。 4.双端队列性能空间效率: 基于数组的双端队列:数组空间结构非常紧凑,效率很高。 基于链表的双端队列:由于链式结构的节点存储了相关联的引用,空间效率比数组结构稍低。 时间效率: 对于双端队列常用的出队、入队操作,由于都是在头尾处进行操作,数组队列和链表队列的执行效率都非常高(时间复杂度(O(1)))。 (编辑:清远站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |

