简体   繁体   English

使用循环数组实现队列:哪种方法可以调整圆形数组的大小?

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

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). 我正在使用循环数组实现一个队列 ,我有点陷入resize()方法实现(当数组已满时)。

Inside the enqueue() method I check if the size of the array equals it's length, and get if it's full. enqueue()方法中,我检查数组的大小是否等于它的长度,如果它已满,则检查它。 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: 我认为它使用for循环,如:

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 然后oldArray = newArray ,返回newArray并调整大小

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? 有人能告诉我是否有更好的方法吗?

For copying arrays with more than a handful of elements, use System.arraycopy() , since it is usually implemented as native code, eg Sun's VM uses hand-coded assembler. 要复制具有多个元素的数组,请使用System.arraycopy() ,因为它通常实现为本机代码,例如Sun的VM使用手工编码的汇编程序。

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;

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. 虽然使用System.arraycopy()方法是最简单有效的解决方案,但我不得不避免使用它并自己实现解决方案。

So, if someone want to resize() a circular array in a queue implementation without System.arraycopy(), here is my final solution: 因此,如果有人想要在没有System.arraycopy()的队列实现中调整圆形数组的大小(),这是我的最终解决方案:

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. Lemme知道该代码是否有任何不便之处。

Regards 问候

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. 然后使用System.arraycopy来完成它。 You should call arraycopy once if front < rear and twice if rear < front. 如果前<后部,则应调用一次arraycopy;如果前部<前部,则应调用两次。

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). 如果你的阵列已经满了,你要么有front == rear - 1 ,要么rear == 0front == length -1 (或者相反,我不知道你的命名法)。 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. 在第二种情况下,您可以一步复制整个数组,在(更一般)第一种情况下,您有两个要复制的块(0 ..前后..长度-1)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM