我正在为学校编写混合数据结构的代码,并正在调试代码。基本上,此结构是双链接列表和数组的组合,其中每个列表节点包含一组设置大小。由于这是一个有序结构,因此必须做出规定,将完整数组识别并分成两个节点。
这是我的代码,用于将节点拆分为两个,然后将父节点的数组值的后半部分复制到子节点。
public Chunk<E> split(Chunk<E> node) {
Chunk<E> newChunk= new Chunk<E>();
newChunk.index= node.index++;
//connect to previous node
node.next= newChunk.next;
newChunk.prev= node.prev;
//connect to next node
newChunk.next= node.next.next;
node.next.prev= newChunk.prev;
//adds the latter half of the array contents to the new node
//and erases the same contents from the old node
for (int i=chunkSize/2; i<node.numUsed; i++) {
newChunk.items[i-chunkSize/2]= node.items[i];
node.items[i]=null;
}
//update capacity counter for both chunks
node.numUsed=chunkSize/2;
newChunk.numUsed= chunkSize/2;
return newChunk;
}
toArray()方法从列表中返回空值,所以我认为这种拆分方法正在发生。
我的问题是:
答案 0 :(得分:2)
要彻底回答这个问题,你应该写一些单元测试。例如:
package so3898131;
import static org.junit.Assert.*;
import org.junit.Test;
public class ChunkTest {
/** Ensure that the simplest possible case works as expected. */
@Test
public void testEmptySplit() {
Chunk<Object> old = new Chunk<Object>();
Chunk<Object> split = old.split(old);
assertEquals(0, split.chunkSize);
assertEquals(0, split.items.length);
assertEquals(0, split.index);
assertEquals(1, old.index);
}
@Test
public void testSplitWithOneItem() {
// TODO: make sure that after splitting one of the chunks contains
// one element, the other none.
}
@Test
public void testSplitWithTwoItems() {
// TODO: make sure that after splitting a chunk with two elements
// each of the new chunks contains exactly one of the elements.
// Use assertSame(..., ...) to check it.
}
}
这会向我发送NullPointerException
,因为node.next
可能是null
,在这种情况下您无法访问node.next.next
。这可能意味着您的代码不起作用。至少它不起作用我期待它。
更新:您的代码不正确。我写了一个像这样的单元测试:
@Test
public void testSplitLinkage() {
Chunk<Object> old = new Chunk<Object>();
assertNull(old.prev);
assertNull(old.next);
Chunk<Object> split = old.split(old);
assertNull(old.prev);
assertSame(split, old.next);
assertSame(old, split.prev);
assertNull(split.next);
}
然后我修改了代码,以便成功运行此测试。我不得不用以下代码替换一些行:
// connect to previous and next node
Chunk<E> one = node, two = newChunk, three = node.next;
one.next = two;
two.prev = one;
two.next = three;
if (three != null)
three.prev = two;
答案 1 :(得分:0)
更好的问题是:“如何通过调试来隔离(追踪)源代码中错误的位置?”
首先,您需要一种方法来重现问题。看来你已经有了。在一个非平凡的代码库中,您将需要对问题进行二进制搜索。在程序执行中有两个点A和B,其中程序在A中处于有效状态但不在B中,选择A和B之间的点C并检查C处的所有内容是否正确。如果是,则错误发生在C和B,其他在A和C之间。递归,直到你把它缩小到代码的一小部分,通常非常明显。
这就留下了如何验证目前执行是否正确的问题。有多种方法可以做到这一点,但在调试器中执行程序,使用断点暂停执行,并检查变量是否包含预期值可能是最有益的。