ホームページ バックエンド開発 C#.Net チュートリアル .NET Framework - 二重リンク リスト (LinkedList) コード分析 (図)

.NET Framework - 二重リンク リスト (LinkedList) コード分析 (図)

Mar 18, 2017 am 11:37 AM



.NETフレームワークのLinkListは双方向リンクリストを実装しています。その実装ソースコードを要約してみましょう。

まず、LinkedList によって提供されるパブリック プロパティとメソッドのマップを確認します:


.NET Framework - 二重リンク リスト (LinkedList) コード分析 (図)

1 LinkedList によって実装される インターフェイス:

public class LinkedList<T> : ICollection<T>, ICollection, IReadOnlyCollection<T>, ISerializable, IDeserializationCallback
ログイン後にコピー

2 LinkedList のグローバル 変数 には、以下が含まれます。

head はカプセル化されたクラスの head ノード です。

        // 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";
ログイン後にコピー

によってカプセル化された各ノードのデータ構造は次のとおりです:

public sealed class LinkedListNode<T>
{   public LinkedListNode(T value);   
//获取LinkedListNode所属的LinkedList
   public LinkedList<T> List { get; }   
   public LinkedListNode<T> Next { get; }   
   public LinkedListNode<T> Previous { get; }   
   //获取节点中包含的值。
   public T Value { get; set; }
}
ログイン後にコピー

3 Constructor:

        public LinkedList() //默认的构造函数
        {
        }        //带有参数的
        public LinkedList(IEnumerable<T> collection)
        {            if (collection == null)
            {                throw new ArgumentNullException(nameof(collection));
            }            foreach (T item in collection)
            {
                AddLast(item);
            }
        }
ログイン後にコピー

IEnumerable 型のコレクションを構築する場合、AddLast ( T) メソッドには、オーバーロードもあり、動作の詳細は次のとおりです:

        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; //结合LinkedListNode看
        }
ログイン後にコピー

上記の 2 つのメソッド、セマンティクスは、特定のノードを挿入し、
空のリストに新しいノードを挿入し、InternalInsertNodeToEmptyList
new を挿入します。空のリスト InternalInsertNodeBefore にノードを追加し、newNode が挿入される前にノードを指定し、新しく挿入されたノードが有効な新しいノードであるかどうかも判断します。

 internal void ValidateNewNode(LinkedListNode<T> node)
        {            if (node == null)
            {                throw new ArgumentNullException(nameof(node));
            }            if (node.list != null)
            {                throw new InvalidOperationException(SR.LinkedListNodeIsAttached);
            }
        }
ログイン後にコピー

同時に、ノードが有効なノードであるかどうかを判断する方法も提供します:

        internal void ValidateNode(LinkedListNode<T> node)
        {            if (node == null)
            {                throw new ArgumentNullException(nameof(node));
            }            if (node.list != this)
            {                throw new InvalidOperationException(SR.ExternalLinkedListNode);
            }
        }
ログイン後にコピー

これは二重リンクリストの重要な内部メソッドです。

InternalInsertNodeToEmptyList 実装の詳細:

        private void InternalInsertNodeToEmptyList(LinkedListNode<T> newNode)
        {
            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 実装の詳細:

        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 リンク リストは当然のことです。これはノードを挿入するパブリック メソッドと切り離すことができません。

        public LinkedListNode<T> AddAfter(LinkedListNode<T> node, T value)
        {
            ValidateNode(node);
            LinkedListNode<T> result = new LinkedListNode<T>(node.list, value);
            InternalInsertNodeBefore(node.next, result);            return result;
        }        public void AddAfter(LinkedListNode<T> node, LinkedListNode<T> newNode)
        {
            ValidateNode(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 = new 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 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;
        }
ログイン後にコピー

5 もう一度見てみましょう。リンク リスト内のすべてのノードをクリアします。ここでは、すべてのノードがメモリをポイントしないように設定します。ヒープを作成し、GC リサイクルを待ちます。

        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 will loop forever
                temp.Invalidate();
            }

            head = null;
            count = 0;
            version++;
        }
ログイン後にコピー

6 にのみ対応します。ノードの一連のインターフェイスの削除は追加と同様なので、詳細は説明しません。

Clear で呼び出されます。は非常に単純です:

        internal void Invalidate()
        {
            list = null;
            next = null;
            prev = null;
        }
ログイン後にコピー

7 ノード値が値として存在するかどうかを判断するには、 Find メソッド

        public bool Contains(T value)
        {            return Find(value) != null;
        }
ログイン後にコピー

Find メソッド実装の詳細を呼び出します。これは、 API と FindLast に似ています。これは二重リンクリストであるため、リンクされたリストを端からたどるだけです、

       public LinkedListNode<T> Find(T value)
        {
            LinkedListNode<T> node = head;            
            //调用默认相等比较器
            EqualityComparer<T> c = EqualityComparer<T>.Default;            
            if (node != null)//链表为null
            {                
            if (value != null) 
                {                    
                do
                    {                        
                    if (c.Equals(node.item, value)) //Equals:某个节点node的item与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; //链表为null,直接返回null
        }
ログイン後にコピー

8 データを array にコピーする実装を見てみましょう :

        public void CopyTo(T[] array, int index)
        {            
        if (array == null)
            {                
            throw new ArgumentNullException(nameof(array));
            }            
            if (index < 0)
            {                
            throw new ArgumentOutOfRangeException(nameof(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); //双向链表,再次遍历到头结点时
            }
        }
ログイン後にコピー

以上が.NET Framework - 二重リンク リスト (LinkedList) コード分析 (図)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

Video Face Swap

Video Face Swap

完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

LinkedList クラスのremoveLast() メソッドを使用して、リンク リストの最後の要素を削除します。 LinkedList クラスのremoveLast() メソッドを使用して、リンク リストの最後の要素を削除します。 Jul 24, 2023 pm 05:13 PM

リンク リストの最後の要素を削除するには、LinkedList クラスの RemoveLast() メソッドを使用します。LinkedList は、Java コレクション フレームワークの一般的なデータ構造です。要素は二重リンク リストの形式で格納されます。 LinkedList クラスが提供するメソッドを使用すると、要素の追加、削除、変更など、リンク リストを簡単に操作できます。シナリオによっては、リンクされたリストの最後の要素を削除する必要がある場合があります。 LinkedList クラスは、removeLas を提供します

LinkedList に要素を追加する Java プログラム LinkedList に要素を追加する Java プログラム Aug 26, 2023 pm 10:21 PM

LinkedList は JavaCollectionFramework の一般クラスで、List、Deque、Queue の 3 つのインターフェイスを実装します。これは、各要素が相互にリンクされている線形データ構造である LinkedList データ構造の機能を提供します。 LinkedList に対して、要素の追加、削除、走査などのさまざまな操作を実行できます。 LinkedList コレクションに要素を追加するには、add()、addFirst()、addLast() などのさまざまな組み込みメソッドを使用できます。これらのメソッドを使用して要素を LinkedList に追加する方法を検討します。 Javaで

C++ を使用した指定サイズによる二重リンクリストのグループ化を逆にする C++ を使用した指定サイズによる二重リンクリストのグループ化を逆にする Sep 04, 2023 am 09:49 AM

この問題では、リンクされたリストの先頭へのポインタと整数 k が与えられます。サイズ k のグループでは、リンクされたリストを逆にする必要があります。たとえば、-Input:1<->2<->3<->4<->5(doublelinkedlist),k=3Output:3<->2<->1<->5<->4 解決策を探します方法 この問題では、この問題を解決するための再帰的アルゴリズムを定式化します。この方法では再帰を使用し、再帰を使用して問題を解決します。例#include<iostream&

Java で LinkedList.addFirst() メソッドを使用してリンク リストの先頭に要素を追加するにはどうすればよいですか? Java で LinkedList.addFirst() メソッドを使用してリンク リストの先頭に要素を追加するにはどうすればよいですか? Nov 18, 2023 pm 03:51 PM

Java の LinkedList クラスは、リンク リストの先頭に要素を追加する addFirst() メソッドを提供します。このメソッドの機能は、リンク リストの先頭に要素を追加し、元のリンク リストの他の要素を元に戻すことです。以下は、LinkedList.addFirst() メソッドを使用してリンク リストの先頭に要素を追加するサンプル コードです。

Java ドキュメントの解釈: LinkedList クラスの addFirst() メソッド関数の分析 Java ドキュメントの解釈: LinkedList クラスの addFirst() メソッド関数の分析 Nov 03, 2023 am 09:09 AM

Java ドキュメントの解釈: LinkedList クラスの addFirst() メソッドの機能分析 LinkedList は、Java コレクション フレームワークの二重リンク リスト実装クラスです。リスト内の追加、削除、検索操作のための一連のメソッドを提供します。その中でも、addFirst() メソッドは、LinkedList クラスの重要なメソッドの 1 つです。この記事では、addFirst() メソッドの機能を詳細に分析し、具体的なコード例を示します。 addFirst() メソッド

JavaでLinkedListを配列に変換するにはどうすればよいですか? JavaでLinkedListを配列に変換するにはどうすればよいですか? Aug 29, 2023 pm 11:09 PM

LinkedList クラスの toArray() メソッドは、現在の LinkedList オブジェクトをオブジェクト型の配列に変換して返します。この配列には、このリスト内のすべての要素が正しい順序 (最初の要素から最後の要素まで) で含まれています。これは、配列ベースの API とコレクションベースの API の間のブリッジとして機能します。そこで、LinkedList を配列に変換し、LinkedList クラスをインスタンス化します。 add() メソッドを使用してデータを設定します。上記で作成したリンク リストで toArray() メソッドを呼び出し、オブジェクトの配列を取得します。オブジェクトの配列の各要素を文字列に変換します。例 importjava.util.Arrays;importjava.uti のリアルタイム デモンストレーション

Java ドキュメントの解釈: LinkedList クラスの addLast() メソッドの機能分析 Java ドキュメントの解釈: LinkedList クラスの addLast() メソッドの機能分析 Nov 03, 2023 pm 02:26 PM

Java ドキュメントの解釈: LinkedList クラスの addLast() メソッドの機能分析 Java コレクション フレームワークでは、LinkedList クラスは二重リンク リストによって実装された List インターフェイスです。 LinkedList クラスは、addLast() メソッドなど、リンク リストを操作するためのメソッドを多数提供します。この記事では、LinkedList の addLast() メソッドを詳細に分析し、具体的なコード例を示します。 addLast() メソッドの機能は、指定された要素を追加することです。

LinkedList クラスのremoveFirstOccurrence() メソッドを使用して、リンク リストに初めて表示される指定された要素を削除します。 LinkedList クラスのremoveFirstOccurrence() メソッドを使用して、リンク リストに初めて表示される指定された要素を削除します。 Jul 24, 2023 pm 04:50 PM

LinkedList クラスの RemoveFirstOccurrence() メソッドを使用して、リンク リストに初めて表示される指定された要素を削除します。リンク リストは、多くのノードで構成される一般的に使用されるデータ構造です。各ノードにはデータ要素と参照が含まれています次のノードへ。 LinkedList クラスは、リンク リストを実装する Java コレクション フレームワークで提供されるクラスで、リンク リストを操作するためのメソッドを豊富に提供します。このうち、removeFirstOccurrence()メソッドが利用できます。

See all articles