我制作了自己的单链/链表。 现在,如果我想从列表中删除/删除节点/项目,我必须做这样的事情:
public void Delete(PARAMETERS)
{
Node previousNode = null,
currentNode = f;
while (currentNode != null)
{
if (SOMECONDITION)
{
if (previousNode == null)
{
f = currentNode.Next;
}
else
{
previousNode.Next = currentNode.Next;
}
}
else
{
previousNode = currentNode;
}
currentNode = currentNode.Next;
}
}
如果SOMECONDITION为真,你只需跳过currentNode就可以有效地“删除”节点,因为没有任何东西可以指向它。
但是,我真的很想知道,为什么我不能做这样的事情:
(...)
while ()
{
if (SOMECONDITION)
{
currentNode = currentNode.Next;
}
currentNode = currentNode.Next;
}
(...)
或许:
(...)
while ()
{
if (SOMECONDITION)
{
currentNode = currentNode.Next.Next;
}
else
{
currentNode = currentNode.Next;
}
}
(...)
我缺乏什么基本理解?
答案 0 :(得分:6)
这样做的:
currentNode = currentNode.Next.Next;
是NullReferenceException的主要候选者
编辑: 这是一个列表实现,其中包含一些可能有助于您理解的图片。 http://www.csharpfriends.com/Articles/getArticle.aspx?articleID=176
答案 1 :(得分:3)
currentNode只是一个临时指针变量(引用),它不再存在于作用域的末尾(即下一个右括号)。当您更改引用所指向的内容时,您不会更改任何其他引用;改变currentNode不会神奇地改变前一节点的Next参考指向的内容。
currentNode = currentNode.Next // only changes the temporary reference
您必须实际进入链接列表并更改列表中的引用,这是您在更改previousNode时所执行的操作。接下来 - 您更改上一个节点认为其下一个节点的节点。你基本上告诉它“这是你的新下一个节点,忘了旧节点。”
此外,正如其他人所说,你应该检查整个空引用。如果currentNode.Next是列表中的最后一个节点,则它的Next将指向任何位置,并且您将获得NullReferenceException。
答案 2 :(得分:2)
没有什么可说的,你不能做Next.Next。
唯一的问题是如果currentNode.Next为null?然后你会得到一个错误。
PreviousNode可以正常工作,因为您在使用之前进行了NULL检查。
答案 3 :(得分:1)
也许如果你重新写一下原文,你会更好地看到你在列表中做了什么。
public void Delete(PARAMETERS)
{
var previous = FindPreviousNode(PARAMETERS);
if( previous == null && Matches(f, PARAMETERS)) {
f = f.Next;
} else if(previous != null ) {
previous.Next = previous.Next.Next;
} // u could add "else { throw new NodeNotFound() }" if that's appropiate
}
private Node FindPreviousNode(PARAMETERS) {
Node currentNode = f;
while (currentNode != null) {
if (Matches(currentNode.Next, PARAMETERS)) {
return currentNode;
}
currentNode = currentNode.Next;
}
return null;
}
你已经在评论中询问了解更多关于列表和Next的属性的内容,所以在这里:
让我们说列表是:1 | 3 | 5 | 7,第一个指向1,1的下一个属性指向3,5个下一个指向7,而7的下一个指向空。这就是你追踪存储列表的全部内容。如果将5的Next属性设置为null,则删除7.如果您将3的Next属性设置为7,则从列表中删除5。如果您先设置为3,则删除1。
关于第一个和下一个属性的全部内容。这就是列表的原因。
答案 4 :(得分:0)
在这两种情况下,你怎么知道currentNode.Next不为null,因此你可以在它上面应用.Next?您只是在循环条件中检查!= null。
答案 5 :(得分:0)
currentNode和previousNode的赋值不会改变链表的结构。它们只是用于逐步完成结构。
对previousNode.Next的赋值是改变结构的原因。执行currentNode = currentNode.Next.Next将跳过下一个节点(如果currentNode.Next不为null),但它不会改变列表的结构。
答案 6 :(得分:0)
如果你想知道这样的问题,你应该真正勾勒出链表的图片。 看要完成某些链表突变需要做什么要容易得多,而不是推理它。
答案 7 :(得分:0)
老实说,我根本不遵守发布的代码。
如果这是标准链接列表(每个节点都有一个Next,但就是这样),请按照以下步骤删除单个项目:
步骤1:找到要删除的目标节点,但跟踪上一个访问过的节点
第2步:prevNode.Next = targetNode.Next
注意:需要进行删除列表头部的特殊检查。