为什么AddLast在C#链接列表中起作用?

JansthcirlU

当我发现我不太了解方法的工作原理时,我正在浏览.NET参考来查看aLinkedList<T>及其相关LinkedListNode<T>元素的内部工作原理我会考虑解决我的困惑。AddLast(T item)AddLast(LinkedListNode<T> node)AddLast(T item)

我的看法是,该方法首先创建一个新节点,该节点引用当前列表并保存需要添加的值。然后,它通过查看head,假设曾经添加到列表中的第一项来检查列表是否为空

A) head 为空

呼叫被叫方法InternalInsertNodeToEmptyList(LinkedListNode<T> newNode),其中newNode在这种情况下将是result从围绕该方法的范围。它检查列表是否实际上为空,然后在将其设置为head列表的之前,修改要添加的节点以双向链接到自身同时更新列表的数量和版本。

private void InternalInsertNodeToEmptyList(LinkedListNode<T> newNode)
{
    Debug.Assert( head == null && count == 0, "LinkedList must be empty when this method is called!");
    newNode.next = newNode; // i.e. result.next = result
    newNode.prev = newNode; // i.e. result.prev = result
    head = newNode; // i.e. head = result
    version++;
    count++;
}
B) head 不为空

呼叫被叫方法InternalInsertNodeBefore(LinkedListNode<T> node, LinkedListNode<T> newNode),其中nodeheadnewNoderesult从围绕这一方法的范围。首先,它检查列表是否不为空,但是添加新节点的实际逻辑如下:

private void InternalInsertNodeBefore(LinkedListNode<T> node, LinkedListNode<T> newNode)
{
    newNode.next = node; // result.next = head
    newNode.prev = node.prev; // result.prev = head.prev (but isn't head.prev just head?)
    node.prev.next = newNode; // head.prev.next = result (so result gets added after head?)
    node.prev = newNode; // head.prev = result (why does head link back to result?)
    version++;
    count++;
}

我真的不明白这如何导致在列表的最后一个已知链接之后插入新链接。为什么这不会导致在头之后而不是最后一个已知链接之后添加链接?

广州7

LinkedList<T> 是一个双向链接列表:每个节点在引用之前和之后都引用了这些节点。

head是列表中的第一个元素,但其prev成员指向列表中的最后一个元素。您可以从Last属性中看到以下内容

public LinkedListNode<T> Last {
    get { return head == null? null: head.prev;}
}

列表的最后一个元素与之间的这种关系head是双向的:head.prev是列表中的最后一个元素,列表中的最后一个元素nexthead

所以:

// Remember that 'node' is the 'head'. I've replaced 'node' with 
// 'head' to make this clearer.

// The new node's 'next' points to 'head', as it should
newNode.next = head;

// The new node's 'prev' points to the old last element in the list
// (remember that 'head.prev' is the last element in the list)
newNode.prev = head.prev; 

// 'head.prev' is the old last element in the list. This is now the second-last
// element in the list, and its 'next' should be our new node. This
// is the reciprocal of 'newNode.prev = head.prev'
head.prev.next = newNode;

// head.prev now points to the new node, as it should. This is the reciprocal of
// 'newNode.next = head'
head.prev = newNode; 

尝试绘制“之前”状态:

                       LinkedList
                            |
                            v 
oldLastNode <-- prev --   head             
             -- next --> 

后:

                                           LinkedList
                                                |
                                                v 
oldLastNode <-- prev --  newNode <-- prev --  head             
             -- next -->          -- next -->

所以我们要做:

oldLastNode.next = newNode
newNode.prev = oldLastNode

newNode.next = head
head.prev = newNode

从第一个图表中,我们可以看到那oldLastNode是旧的head.prev因此,只要我们head.prev在重新分配之前进行更改head.prev,我们就可以这样写:

head.prev.next = newNode
newNode.prev = head.prev

newNode.next = head
head.prev = newNode

这些操作与您的问题相同,但已重新安排。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

为什么隐藏方法在C#中不起作用

out 参数在 C# 中不起作用。为什么?

为什么我的模板链接列表不起作用?

为什么我的链接列表中的排序功能(通过交换数据排序)不起作用

为什么 vuetify 中嵌套的 nuxt 链接不起作用?

Append在C ++中的数组链接列表中不起作用

为什么map_if()在列表中不起作用

为什么从列表中删除零不起作用?

为什么链接诺言不起作用?

.then 链接不起作用。为什么?

为什么我的更新查询在SQL Server的C#中不起作用?

为什么简单的DateTime转换在ASP.NET C#中不起作用?

为什么Bloch的Builder模式在C#中不起作用

为什么SQL逻辑运算符在c#命令中不起作用?

链接列表:推送:请解释为什么此代码不起作用

为什么从 C# 运行时 python 中的相对路径不起作用,但在 C# 之外使用相同的解释器时却起作用?

为什么我的列表不起作用

如果条件在c中起作用,为什么在printf里面?

为什么 C 中的这个 while 循环不起作用?

为什么退格键'\ b'在C ++中不起作用?

为什么此C代码在JavaScript中不起作用?

为什么序列迭代在C宏中起作用?

C ++中的多态性为什么不起作用?

为什么const指针的向量在c ++ 17中起作用

为什么“函数尝试”在 C++ 中不起作用?

为什么if else结构在c ++中不起作用?

链表(在C中)为什么不起作用

为什么 strcmp 在 c 中不起作用?

为什么 if 语句在 C++ 函数中不起作用?