自己动手实现java数据结构(四)双端队列
|
扩容代码的实现:
* 内部数组扩容
* expand(){
:::内部数组 扩容两倍
int elementsLength = .elements.length;
Object[] newElements = new Object[elementsLength * EXPAND_BASE];
:::将"head -> 数组尾部"的元素 复制在新数组的前面 (tips:使用System.arraycopy效率更高)
for(int i=this.head,j=0; i<elementsLength; i++,j++){
newElements[j] = .elements[i];
}
:::将"0 -> head"的元素 复制在新数组的后面 (tips:使用System.arraycopy效率更高)
int i=0,j=elementsLength-this.head; i<this.head; i++,1)">:::初始化head,tail下标
this.tail = :::内部数组指向 新扩容的数组
this.elements = newElements;
}
扩容操作时间复杂度: 动态扩容的操作由于需要进行内部数组的整体copy,其时间复杂度是O(n)。 但是站在全局的角度,动态扩容只会在入队操作导致空间不足时偶尔的被触发,整体来看,动态扩容的时间复杂度为O(1)。 3.1.6 其它接口实现: size() {
return getMod(tail - head);
}
@Override
isEmpty() {
:::当且仅当 头尾下标相等时 队列为空
return (head == tail);
}
@Override
clear() {
int head = .head;
int tail = .tail;
while(head !=this.elements[head] = ;
head = getMod(head + 1);
}
;
}
@Override
public Iterator<E> iterator() {
return Itr();
}
3.1.7 基于数组的双端队列——迭代器实现:迭代器从头部元素开始迭代,直至尾部元素终止。 值得一提的是,虽然队列的api接口中没有提供直接删除队列中间(非头部、尾部)的元素,但是迭代器的remove接口却依然允许这种操作。由于必须要时刻保持队列内元素排布的连续性,因此在删除队列中间的元素后,需要整体的移动其他元素。 此时,有两种选择: 方案一:将"头部下标"到"被删除元素下标"之间的元素整体向右平移一位 方案二:将"被删除元素下标"到"尾部下标"之间的元素整体向左平移一位 我们可以根据被删除元素所处的位置,计算出两种方案各自需要平移元素的数量,选择平移元素数量较少的方案,进行一定程度的优化。 队列迭代器的remove操作中存在一些细节值得注意,我们使用一个简单的例子来帮助理解: 1. 当前队列在迭代时需要删除元素"7"(红色元素),采用方案一需要整体平移(1,2,3,4,5,6)六个元素,而方案二只需要整体平移(8,9,10,11,12)五个元素。因此采用平移元素更少的方案二, 2. 这时由于(8,9,10,11,12)五个元素被物理上截断了,所以主要分三个步骤进行平移。 第一步: 先将靠近尾部的 (8,9)两个元素整体向左平移一位(蓝色元素) 第二步: 将内部数组头部的元素(10),复制到内部数组的尾部(粉色元素) 第三部 :? 将剩下的元素(11,12),整体向左平移一位(绿色元素) remove操作执行前:
remove操作执行后:
迭代器代码实现: (编辑:网站开发网_盐城站长网 ) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |



