. NET Framework-bidirectional linked list (LinkedList) code Analysis

Source: Internet
Author: User


. NET Framework of the linklist, the realization of a doubly linked list, summed up its implementation of the source code.

Let's take a look at the map of the public properties and methods provided by LinkedList:



1 interfaces implemented by LinkedList:

public class linkedlist<t>: Icollection<t>, ICollection, Ireadonlycollection<t>, ISerializable, Ideserializationcallback

The global variables of the 2 linkedlist include,

Head is the encapsulated head node in the class;

        This linkedlist is a doubly-linked circular list.        Internal linkedlistnode<t> head;                internal int count;                internal int version;                Private object _syncroot;                A temporary variable which we need during deserialization.          Private SerializationInfo _siinfo;         Names for serialization        Private Const string versionname = "Version";                Private Const string countname = "Count";          Private Const string valuesname = "Data";

The data structure for each of the encapsulated nodes is:

public sealed class linkedlistnode<t>{public   LinkedListNode (T value);   Gets the LinkedList public   linkedlist<t> List {get linkedlistnode belongs to;      Public linkedlistnode<t> Next {get;}      Public linkedlistnode<t> Previous {get;}      Gets the value contained in the node. Public   T Value {get; set;}}

3 Constructors:

        Public LinkedList ()//default constructor        {        }//Public        LinkedList with Parameters        (ienumerable<t> collection)        {            if (collection = = null)            {                throw new ArgumentNullException (Nameof (collection));            }            foreach (T item in collection)            {                addlast (item);            }        }

When constructing the IEnumerable type of collection, the AddLast (T) method is used, and it has an overload with the following working details:

        Public linkedlistnode<t> addlast (T value)        {            linkedlistnode<t> result = new Linkedlistnode<t > (this, value);                        if (head = = null)            {                internalinsertnodetoemptylist (result);            }            else            {                Internalinsertnodebefore (head, result);            }            return result;        }                public void AddLast (linkedlistnode<t> node)        {            Validatenewnode (node);                        if (head = = null)            {                internalinsertnodetoemptylist (node);            }            else            {                Internalinsertnodebefore (Head, node);            }            Node.list = this; Combine LinkedListNode to see        }

The 2 methods above, the semantics is to insert a node,
Insert a new node into the empty list, internalinsertnodetoemptylist
Inserts a new node into the list that is not empty, internalinsertnodebefore, and gives the node before which the NewNode is inserted, and also determines whether the newly inserted node is a valid new node.

internal void Validatenewnode (linkedlistnode<t> node)        {            if (node = = null)            {                throw new ArgumentNullException (nameof (node));            }            if (node.list! = null)            {                throw new InvalidOperationException (SR. linkedlistnodeisattached);            }        }

At the same time, we also determine whether a node is a valid node:

        internal void Validatenode (linkedlistnode<t> node)        {            if (node = = null)            {                throw new ArgumentNullException (nameof (node));            }            if (node.list! = this)            {                throw new InvalidOperationException (SR. Externallinkedlistnode);            }        }

This is an important internal method of the doubly linked list,

Implementation details of the internalinsertnodetoemptylist:

        private void Internalinsertnodetoemptylist (linkedlistnode<t> newNode)        {            Debug.Assert (head = = NULL && count = = 0, "LinkedList must was empty when this method is called!");            Newnode.next = NewNode;            Newnode.prev = NewNode;            head = NewNode;            version++;            count++;        }

Implementation details of the Internalinsertnodebefore:

        private void Internalinsertnodebefore (linkedlistnode<t> node, linkedlistnode<t> newNode)        {            newnode.next = node;            Newnode.prev = Node.prev;            Node.prev.next = NewNode;            Node.prev = NewNode;            version++;            count++;        }

4 linked lists are naturally inseparable from the public method of inserting a node,

        Public linkedlistnode<t> Addafter (linkedlistnode<t> node, T value) {Validatenode (no            DE);            linkedlistnode<t> result = new Linkedlistnode<t> (node.list, value);            Internalinsertnodebefore (node.next, result);        return result; } public void Addafter (linkedlistnode<t> node, linkedlistnode<t> newNode) {Validaten            Ode (node);            Validatenewnode (NewNode);            Internalinsertnodebefore (Node.next, NewNode);        Newnode.list = this; } public linkedlistnode<t> Addbefore (linkedlistnode<t> node, T value) {Validatenode (            node);            linkedlistnode<t> result = new Linkedlistnode<t> (node.list, value);            Internalinsertnodebefore (node, result);            if (node = = head) {head = result;        } return result; } public void Addbefore (Linkedlistnode<t> node, linkedlistnode<t> newNode) {validatenode (node);            Validatenewnode (NewNode);            Internalinsertnodebefore (node, newNode);            Newnode.list = this;            if (node = = head) {head = NewNode; }} public linkedlistnode<t> AddFirst (T value) {linkedlistnode<t> result = NE                        W linkedlistnode<t> (this, value);            if (head = = null) {internalinsertnodetoemptylist (result);                } else {Internalinsertnodebefore (head, result);            Head = result;        } return result;            } public void AddFirst (linkedlistnode<t> node) {Validatenewnode (node);            if (head = = null) {internalinsertnodetoemptylist (node); } else {inTernalinsertnodebefore (head, node);            Head = node;        } node.list = this; Public linkedlistnode<t> addlast (T value) {linkedlistnode<t> result = new Linkedli                        Stnode<t> (this, value);            if (head = = null) {internalinsertnodetoemptylist (result);            } else {Internalinsertnodebefore (head, result);        } return result;            } public void AddLast (linkedlistnode<t> node) {Validatenewnode (node);            if (head = = null) {internalinsertnodetoemptylist (node);            } else {Internalinsertnodebefore (Head, node);        } node.list = this; }

5 Look again, clear the list of all nodes, here is set all nodes are not pointing to the memory heap, and so on GC recycle,

        public void Clear ()        {            linkedlistnode<t>-current = head;                        while (current! = null)            {                linkedlistnode<t> temp = current;                Current = current. Next;                   Use next the instead of "next", otherwise it'll loop forever                temp. Invalidate ();            }            head = NULL;            Count = 0;            version++;        }

6 corresponds only to the removal of a node of some of the column interface, and add a similar, no longer repeat,

Clear inside calls the invalidate (), the implementation is very simple:

        internal void Invalidate ()        {            list = null;            next = null;            prev = null;        }

7 Determine the existence of a node value as value, which calls the Find method,

        public bool Contains (T value)        {            return Find (value)! = null;        }

The Find method implements the details, similar APIs have findlast, because it is a doubly linked list, so from the end of the chain to go through the list,

       Public linkedlistnode<t> Find (T value) {linkedlistnode<t> node = head; Call the default equality comparer equalitycomparer<t> C = equalitycomparer<t>.                        Default;                                    if (node! = NULL)//The linked list is null {if (value! = null) { do {if (C.equals (Node.item, value))//equa                        LS: The item of a node is equal to value {return node;                    } node = Node.next;                } while (node! = head);                                            } else {do {                                                    if (Node.item = = null) {       return node;                  } node = Node.next;                } while (node! = head); }} return null; The linked list is NULL, directly returning NULL}

8 Look at a copy of the data to the array implementation:

        public void CopyTo (t[] array, int index) {if (array = = NULL) {            throw new ArgumentNullException (nameof (array)); } if (Index < 0) {throw new ArgumentOutOfRangeException (n Ameof (index), index, SR.            Argumentoutofrange_neednonnegnum); } if (Index > array. Length) {throw new ArgumentOutOfRangeException (nameof (index), index, SR.)            Argumentoutofrange_biggerthancollection); } if (array. Length-index < Count) {throw new ArgumentException (SR.)            Arg_insufficientspace);                        } linkedlistnode<t> node = head;                    if (node! = null) {do {array[index++] = Node.item;             node = Node.next;   } while (node! = head); Doubly linked list, when traversing the head node again}}
Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.