算法4 Java解答 2.4.22
2.4.2
问题:
2.4.22 Array resizing. Add array resizing to MaxPQ, and prove bounds like those of Proposition Q for array accesses, in an amortized sense.
调整数组的大小。在MaxPQ中加入调整数组大小的代码,并和命题Q一样证明对于一般性长度为N的队列数组访问的上限。
分析:
在MaxHeap类中新增方法 resize(int max),当堆的中元素个数等于key数组容量满的时候,key数组增大两倍,当堆的元素个数等于key数组长度的1/4时,key数组长度变为原来的1/2.
public _MaxMQ(){
this(1);
}
private void resize(int max){
assert max > N;
Comparable[] temp = new Comparable[max];
for(int i=1; i<=N; i++){
temp[i] = pq[i];
}
pq = (Key[]) temp;
}
public Key delMax(){
Key max = pq[1];
pq[1] = pq[N--]; // 使用 pq[N] 作为哨兵
sink(1);
pq[N + 1] = null;
if(N==(pq.length-1)/4) resize(pq.length/2);
assert isMaxHeap();
return max;
}
public void insert(Key v){
// double size of array is necessary
if(N==(pq.length-1)) resize(pq.length*2);
pq[++N] = v;
swim(N);
}
public static void main(String[] args) {
for(int i=0; i<3; i++){
_MaxMQ<Integer> pq = new _MaxMQ<>();
Integer[] a = ascIntArray(10*i);
for(int j=0; j<a.length; j++){
pq.insert(j);
}
while (!pq.isEmpty()){
StdOut.printf("%5d\t", pq.delMax());
}
StdOut.println();
}
}
// 9 8 7 6 5 4 3 2 1 0
// 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
Proposition Q.
In an N-key priority queue,
the heap algorithms require no more than 1 + lg N compares for insert
and no more than 2 lg N compares for remove the maximum.
统计插入一个元素需要访问的数组次数,包括比较和交换 (2+3)lgN + 1
使用resize,统计插入一个元素均摊下来数组的访问次数
总的数组访问次数,2+4+8+…+2^lgN = 2^(lgN + 2)-1 = 4N - 1
对于一次插入:为 4-1/N
所以对于插入,需要的数组访问次数上限为 5lgN + 5 - 1/N
参考:
https://algs4.cs.princeton.edu/24pq/MaxPQ.java.html
https://alg4.ikesnowy.com/2-4-22/
https://github.com/YangXiaoHei/Algorithms/blob/master/Ch_2_4_Priority_Queues/Practise_2_4_22.java