在循环队列的扩容/缩容方法中,改变for循环的问题
来源:3-7 循环队列的实现
慕的地9541928
2018-05-29
老师,我是一名计算机语言的初学者,一些问题可能对于其他人而言比较简单,但我不容易理解,希望老师耐心解答; 1、我在resize方法中,改变了原有的for循环,采用toString方法中的循环语句,发现在缩容时会产生一个问 题,就是取出的元素不是front指向的元素,而是tile端的元素;于是我将front=0和tile=size注释掉后,这个 问题就解决了,但在扩容时,又产生了新的问题,就是扩容后,原有的值全变为空值了。这是什么原因呢? 2、在原有的for循环中如果不维护front以及tile的值,为什么也会出错呢? 3、我改写后的代码如下: private void resize(int newCapacity){ E[] newData = (E[])new Object[newCapacity +1]; // for(int i= 0;i<size;i++){ // newData[i] = data[(front+i)%data.length]; // } for (int i = front; i != tile; i=(i+1)%data.length){ newData[i] = data[i]; } data = newData; // front =0; // tile = size; }
1回答
-
你所写的代码(16-18行),其实无论是扩容,还是缩容,都可能产生问题。只是在缩容中更容易表现出来,被你观察到了:)
在这里,首先要明确一下我们二者的代码逻辑的区别。
我的代码,是将原来data[front...tail)(可循环)范围内的元素,放到新的数组的newData[0...size)的范围中。
你的代码,是将原来data[front...tail)(可循环)范围内的元素,放到新的数组的newData[front...tail)中。
但是这样会出问题,比如,在原数组中,有8个空间,有2个元素,存储在data[4], data[5]的位置。
现在缩容后,newData只有4个空间,即对于newData来说,合法的索引值只有0, 1, 2, 3。此时,你的代码就产生了Bug,因为在你的for循环中,i的索引值是相对data来说的,但是对data合法的i,对newData不一定合法:)
希望你已经了解了你的代码的bug在哪里。如果还不是很清楚,不妨对于你发现问题的测试用例,仔细跟踪看一看:)
----------
正因为如此,我们在缩容后(其实扩容也有可能出现同样的问题),并不能使用原有的data的索引系统。也因此,在我的代码中,我直接将原有的data中的元素,在data[front...tail)(可循环)范围内,放到了新的newData数组的newData[0...size)的范围中。相应的,front和tail也要进行重新的维护。
再回顾我的代码。在我的代码中,for循环中,i的索引值是相对newData来说的,所以有newData[i] = data[(front+i)%data.length],这里的(front+i)%data.length,其实是将每一个newData中的i,转换成了data中相应的索引,使得原来data中的元素,被放置在了newData[0...size)的范围中。
事实上,你也可以在for循环中使用data的索引系统,在赋值的时候,转换成newData中相应的索引。但会稍微麻烦一些。如果有兴趣的话,不妨试试看?:)
012018-05-30
相似问题