【C#.NET解説】高速な挿入・削除操作が可能なLinkedListクラスを天空の女神が解説

2024年12月3日火曜日

コレクション

t f B! P L

名前空間 System.Collections.Generic

LinkedList

自己紹介

こんにちは、私は天空を司る女神です。この広大な空を見渡しながら、今日は「C#.NET」のLinkedListクラスについてお話しします。LinkedListクラスは、データの管理をより柔軟かつ効率的に行えるように設計されたクラスです。ぜひ、私と一緒にその魅力に触れていきましょう!

基本機能

LinkedListクラスは、要素を線形に管理するデータ構造で、双方向にリンクされたリストを表現します。このリストは、要素の追加や削除が迅速に行えるという特徴を持っています。以下に簡単なサンプルコードを示します。

C#
using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        // LinkedListを作成
        LinkedList<string> linkedList = new LinkedList<string>();

        // 要素を追加
        linkedList.AddLast("天空");
        linkedList.AddLast("大地");
        linkedList.AddFirst("宇宙");

        // リストの内容を表示
        foreach (var item in linkedList)
        {
            Console.WriteLine(item); // 宇宙 天空 大地
        }
    }
}

使う場面の注意点

LinkedListは効率的な操作を提供しますが、特定のシナリオでの使用には注意が必要です。たとえば、ランダムアクセスが必要な場合は、ArrayやListの方が適しています。以下に注意点を示すコードを記載します。

C#
using System;
using System.Collections.Generic;
using System.Diagnostics;

class Program
{
    static void Main()
    {
        const int size = 100000;
        List<int> list = new List<int>(size);
        LinkedList<int> linkedList = new LinkedList<int>();

        for (int i = 0; i < size; i++)
        {
            list.Add(i);
            linkedList.AddLast(i);
        }

        // List<T> のランダムアクセス
        Stopwatch sw = Stopwatch.StartNew();
        for (int i = 0; i < size; i++)
        {
            int value = list[i];
        }
        sw.Stop();
        Console.WriteLine($"List<T> のランダムアクセス時間: {sw.ElapsedMilliseconds} ms");

        // LinkedList<T> のランダムアクセス
        sw.Restart();
        LinkedListNode<int> node = linkedList.First;
        for (int i = 0; i < size; i++)
        {
            int value = node.Value;
            node = node.Next;
        }
        sw.Stop();
        Console.WriteLine($"LinkedList<T> のランダムアクセス時間: {sw.ElapsedMilliseconds} ms");
    }
}

プロパティとその活用方法

LinkedListクラスの必要なメソッドやプロパティを示すコード例を、各メソッドやプロパティに日本語のコメントを付けて書きます。

C#
using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        // LinkedListを作成
        LinkedList<int> linkedList = new LinkedList<int>();

        // AddFirstメソッド: リストの最初に要素を追加
        linkedList.AddFirst(1);
        // AddLastメソッド: リストの最後に要素を追加
        linkedList.AddLast(3);

        // AddBeforeメソッド: 指定したノードの前に要素を追加
        LinkedListNode<int> node = linkedList.Find(3);
        if (node != null)
        {
            linkedList.AddBefore(node, 2);
        }

        // AddAfterメソッド: 指定したノードの後に要素を追加
        if (node != null)
        {
            linkedList.AddAfter(node, 4);
        }

        // Findメソッド: 指定した値を持つ最初のノードを探す
        LinkedListNode<int> foundNode = linkedList.Find(2);
        if (foundNode != null)
        {
            Console.WriteLine($"値2を含むノードが見つかりました: {foundNode.Value}");
        }

        // Removeメソッド: 指定した値を持つ最初のノードを削除
        linkedList.Remove(2);

        // RemoveFirstメソッド: リストの最初のノードを削除
        linkedList.RemoveFirst();

        // RemoveLastメソッド: リストの最後のノードを削除
        linkedList.RemoveLast();

        // Countプロパティ: リスト内のノード数を取得
        int count = linkedList.Count;
        Console.WriteLine($"リストのノード数: {count}");

        // Firstプロパティ: リストの最初のノードを取得
        LinkedListNode<int> firstNode = linkedList.First;
        if (firstNode != null)
        {
            Console.WriteLine($"最初のノードの値: {firstNode.Value}");
        }

        // Lastプロパティ: リストの最後のノードを取得
        LinkedListNode<int> lastNode = linkedList.Last;
        if (lastNode != null)
        {
            Console.WriteLine($"最後のノードの値: {lastNode.Value}");
        }

        // Clearメソッド: リストの全ノードを削除
        linkedList.Clear();
        Console.WriteLine($"リストをクリアしました。ノード数: {linkedList.Count}");
    }
}

具体的な使い方

LinkedListを利用して、特定のシナリオでどのように動作するか見ていきます。

C#
using System;
using System.Collections.Generic;

public class Employee
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Department { get; set; }

    public Employee(int id, string name, string department)
    {
        Id = id;
        Name = name;
        Department = department;
    }

    public override string ToString()
    {
        return "ID: " + Id + ", Name: " + Name + ", Department: " + Department;
    }
}

public class EmployeeManager
{
    private LinkedList<Employee> employees;

    public EmployeeManager()
    {
        employees = new LinkedList<Employee>();
    }

    // 新しい従業員を追加
    public void AddEmployee(Employee employee)
    {
        employees.AddLast(employee);
    }

    // 従業員をIDで検索
    public Employee FindEmployeeById(int id)
    {
        foreach (var employee in employees)
        {
            if (employee.Id == id)
                return employee;
        }
        return null; // 見つからなかった場合
    }

    // 従業員をIDで削除
    public bool RemoveEmployeeById(int id)
    {
        var node = employees.First;
        while (node != null)
        {
            if (node.Value.Id == id)
            {
                employees.Remove(node);
                return true;
            }
            node = node.Next;
        }
        return false; // 見つからなかった場合
    }

    // 全従業員を一覧表示
    public void PrintAllEmployees()
    {
        foreach (var employee in employees)
        {
            Console.WriteLine(employee);
        }
    }
}

class Program
{
    static void Main()
    {
        EmployeeManager manager = new EmployeeManager();

        // 新しい従業員を追加
        manager.AddEmployee(new Employee(1, "Alice", "HR"));
        manager.AddEmployee(new Employee(2, "Bob", "IT"));
        manager.AddEmployee(new Employee(3, "Charlie", "Finance"));

        // 全従業員を表示
        Console.WriteLine("全従業員の一覧:");
        manager.PrintAllEmployees();

        // 従業員をIDで検索
        Console.WriteLine("\nID 2の従業員を検索:");
        Employee employee = manager.FindEmployeeById(2);
        if (employee != null)
        {
            Console.WriteLine(employee);
        }
        else
        {
            Console.WriteLine("従業員が見つかりませんでした。");
        }

        // 従業員をIDで削除
        Console.WriteLine("\nID 2の従業員を削除:");
        bool removed = manager.RemoveEmployeeById(2);
        if (removed)
        {
            Console.WriteLine("従業員を削除しました。");
        }
        else
        {
            Console.WriteLine("従業員が見つかりませんでした。");
        }

        // 削除後の全従業員を表示
        Console.WriteLine("\n削除後の全従業員の一覧:");
        manager.PrintAllEmployees();
    }
}

解説

具体的なコードで使用した例を振り返ってみましょう。この例では、Findメソッドを活用して特定のノードを見つけ、その前後に新しい要素を挿入しました。このように、LinkedListは柔軟で直感的なデータ操作を可能にします。

LinkedListを使えば、動的にデータを管理しながら、効率的にデータを操作する方法を学べます。ぜひ活用してみてください!

このブログを検索

QooQ