.NETLinkList in the framework implements a two-way linked list. Let’s summarize its implementation source code.
Let’s first look at the map of the public properties and methods provided by LinkedList:
Interface implemented by LinkedList:
public class LinkedList: ICollection , ICollection, IReadOnlyCollection , ISerializable, IDeserializationCallback
variables of LinkedList include,
head is the head node in the encapsulated class; // This LinkedList is a doubly-Linked circular list.
internal LinkedListNode
public sealed class LinkedListNode{ public LinkedListNode(T value); //获取LinkedListNode所属的LinkedList public LinkedList List { get; } public LinkedListNode Next { get; } public LinkedListNode Previous { get; } //获取节点中包含的值。 public T Value { get; set; } }
3
Constructor: public LinkedList() //默认的构造函数
{
} //带有参数的
public LinkedList(IEnumerable
. The working details are as follows: public LinkedListNode
Insert new nodes into non-empty lists, InternalInsertNodeBefore, and give the node before which newNode is inserted, and also judge The newly inserted node is not a valid new node.
internal void ValidateNewNode(LinkedListNodenode) { if (node == null) { throw new ArgumentNullException(nameof(node)); } if (node.list != null) { throw new InvalidOperationException(SR.LinkedListNodeIsAttached); } }
internal void ValidateNode(LinkedListNodenode) { if (node == null) { throw new ArgumentNullException(nameof(node)); } if (node.list != this) { throw new InvalidOperationException(SR.ExternalLinkedListNode); } }
This is an important internal method of a doubly linked list,
InternalInsertNodeToEmptyList implementation details:
private void InternalInsertNodeToEmptyList(LinkedListNodenewNode) { Debug.Assert(head == null && count == 0, "LinkedList must be empty when this method is called!"); newNode.next = newNode; newNode.prev = newNode; head = newNode; version++; count++; }
InternalInsertNodeBefore implementation details:
private void InternalInsertNodeBefore(LinkedListNodenode, LinkedListNode newNode) { newNode.next = node; newNode.prev = node.prev; node.prev.next = newNode; node.prev = newNode; version++; count++; }
4 A linked list is naturally inseparable from the public method of inserting a node,
public LinkedListNodeAddAfter(LinkedListNode node, T value) { ValidateNode(node); LinkedListNode result = new LinkedListNode (node.list, value); InternalInsertNodeBefore(node.next, result); return result; } public void AddAfter(LinkedListNode node, LinkedListNode newNode) { ValidateNode(node); ValidateNewNode(newNode); InternalInsertNodeBefore(node.next, newNode); newNode.list = this; } public LinkedListNode AddBefore(LinkedListNode node, T value) { ValidateNode(node); LinkedListNode result = new LinkedListNode (node.list, value); InternalInsertNodeBefore(node, result); if (node == head) { head = result; } return result; } public void AddBefore(LinkedListNode node, LinkedListNode newNode) { ValidateNode(node); ValidateNewNode(newNode); InternalInsertNodeBefore(node, newNode); newNode.list = this; if (node == head) { head = newNode; } } public LinkedListNode AddFirst(T value) { LinkedListNode result = new LinkedListNode (this, value); if (head == null) { InternalInsertNodeToEmptyList(result); } else { InternalInsertNodeBefore(head, result); head = result; } return result; } public void AddFirst(LinkedListNode node) { ValidateNewNode(node); if (head == null) { InternalInsertNodeToEmptyList(node); } else { InternalInsertNodeBefore(head, node); head = node; } node.list = this; } public LinkedListNode AddLast(T value) { LinkedListNode result = new LinkedListNode (this, value); if (head == null) { InternalInsertNodeToEmptyList(result); } else { InternalInsertNodeBefore(head, result); } return result; } public void AddLast(LinkedListNode node) { ValidateNewNode(node); if (head == null) { InternalInsertNodeToEmptyList(node); } else { InternalInsertNodeBefore(head, node); } node.list = this; }
5 Let’s look at it again, clearing all nodes in the linked list, here It is to set all nodes to no longer point to the memory heap, and then wait for GC recycling,
public void Clear() { LinkedListNodecurrent = head; while (current != null) { LinkedListNode temp = current; current = current.Next; // use Next the instead of "next", otherwise it will loop forever temp.Invalidate(); } head = null; count = 0; version++; }
6 Corresponding to only is to remove a series of interfaces of a certain node, which is similar to adding, and will not be repeated,
Clear calls Invalidate(), and the implementation is very simple:
internal void Invalidate() { list = null; next = null; prev = null; }
7 To determine the existence of a node value as value, it calls the
Find method, public bool Contains(T value)
{ return Find(value) != null;
}
and FindLast, because it is a two-way linked list, so just traverse the linked list from the end, public LinkedListNode
The above is the detailed content of .NET Framework-Doubly Linked List (LinkedList) Code Analysis (Figure). For more information, please follow other related articles on the PHP Chinese website!