自己动手实现java数据结构(四)双端队列(3)
发布时间:2021-04-01 05:02 所属栏目:53 来源:网络整理
导读:在remove操作中有多种可能的情况,由于思路相通,可以通过上面的举例说明帮助理解。 /** * 双端队列 迭代器实现 * private class Itr implements IteratorE { * 当前迭代下标 = head * 代表遍历从头部开始 * */ int
在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)))。 需要注意的是,由于双端队列的迭代器remove接口允许删除队列中间部位的元素,而删除中间队列元素的效率很低(时间复杂度O(n)),所以在使用迭代器remove接口时需要谨慎。 5.双端队列总结(编辑:ASP站长网) |
相关内容
网友评论
推荐文章
热点阅读