Queue implementation with circular arrays: Which is the best way to resize a circular array?

好久不见. 提交于 2019-12-22 10:13:11

问题


I'm implementing a queue using a circular array, and I'm kind of stuck in the resize() method implementation (when the array is full).

Inside the enqueue() method I check if the size of the array equals it's length, and get if it's full. Now, instead of throwing an exception, I'm trying to resize the array.

The thing is, I have two cases to consider

  1. front <= rear
  2. rear < front

Which is the best way to copy the elements of the old array into the new, larger one?

I thought it using a for-loop, like:

newArray = new Array[oldArray.length*2];

if (front <= rear) {
    for (int i = front; i < rear; i++) {
        newArray[i] = oldArray[i];
    } 
} else {
    for (int i = front; i < newArray.length; i++) {
        newArray[i] = oldArray[i];
    }

    for (int j = rear; j < front; j++) {
        // i'm using the variable i, the order is maintained
        newArray[i] = oldArray[j];
        i++;
    }
}

Then oldArray = newArray, return newArray and the resize it's done

I'm not sure of the amount of for's used to do this and I'm afraid I lose values.

Can someone tell me if there is a better way to do this?


回答1:


For copying arrays with more than a handful of elements, use System.arraycopy(), since it is usually implemented as native code, e.g. Sun's VM uses hand-coded assembler.

front > rear

Since the data is contiguous, it can remain in the same place in the new array.

System.arraycopy(oldArray, front, newArray, front, front-rear);

front <= rear

The data is non-contiguous, so copy both blocks to the start of the new array.

// copy [rear to end]
System.arraycopy(oldArray, rear, newArray, 0, oldArray.length-rear);
// copy [0 to front]
System.arraycopy(oldArray, 0, newArray, oldArray.length-rear, front);
front = oldArray.length-(rear-front);
rear = 0;



回答2:


Thx a lot for your answers and different solutions! :)

Although using the System.arraycopy() method is the most easy and efficient solution, I had to avoid using it and implement a solution by myself.

So, if someone want to resize() a circular array in a queue implementation without System.arraycopy(), here is my final solution:

private void resize() {

    E[] aux = (E[]) new Object[Q.length * 2]; // new array

    int i = 0; // use this to control new array positions
    int j = f; // use this to control old array positions

    boolean rearReached = false;

    while (!rearReached) {

        rearReached = j % Q.length == r; // is true if we've reached the rear

        aux[i] = Q[j % Q.length];

        i++;
        j++;

    }

    f = 0;
    r = Q.length - 1;
    Q = aux;

}

As you can see, I took advantage of the "circular" thing and mapped the positions of the old array to the new array using the % operator.

The resultant array will have the double of capacity and all the elements (keeping the original order, obviously) at the beginning of the new array.

I've tested it and it worked properly. Lemme know if there is any inconvenience with that code.

Regards




回答3:


Think of the blocks of array elements you want to move and where they should go in the new array. Then and use System.arraycopy to do it. You should call arraycopy once if front < rear and twice if rear < front.




回答4:


If your array is full, you either have front == rear - 1, or rear == 0 and front == length -1 (or the other way around, I don't know your nomenclature). In the second case you can copy your whole array in one step, in the (more general) first case you have two blocks (0 .. front and rear .. length-1) which are to copy.



来源:https://stackoverflow.com/questions/5695042/queue-implementation-with-circular-arrays-which-is-the-best-way-to-resize-a-cir

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!