C# PR

【C#】Queue(キュー)ってなに?使い方とサンプルプログラム

アイキャッチ(c_sharp)
記事内に商品プロモーションを含む場合があります

C#でデータ構造を扱う際、Queue(キュー)は非常に便利なコレクションの一つです。
日常生活で行列を思い浮かべるとわかりやすいかもしれません。
例えば、銀行での順番待ちや、レストランでの待ち行列など、先に来たものから順に処理されるシステムは、キューの典型的な使用例です。

プログラミングの世界でも、この「先入れ先出し」(FIFO: First In, First Out) の原則を利用するさまざまなシチュエーションがあります。
C#のQueueクラスは、このような場面で非常に有効で、シンプルかつ直感的な操作でデータの追加や削除が可能です。

この記事では、Queueの基本的な特徴と使い方、さらにはいくつかのサンプルプログラムを通じて、C#でのQueueの活用方法について詳しく解説していきます。

Queue(キュー)とは

Queue(キュー)とは、先に格納されたデータが先に取り出される「先入れ先出し」(FIFO: First In, First Out) のデータ構造を指します。
C#では、System.Collections.Generic名前空間にあるQueue<T>クラスを使って、このデータ構造を簡単に実装できます。
ジェネリック型<T>を使用することで、任意の型のオブジェクトをキューに格納できるため、柔軟かつ型安全なコーディングが可能です。

Queueの利用は、コードの明瞭さと効率性を向上させるための重要な仕組みです。
特に、データの順序が業務ロジックにとって重要な場合、Queueを適切に活用することでプログラムの可読性と保守性が大幅に向上します。

Queueの主な使い方

Queueに新しい要素を追加する(Enqueue)

Queueクラスで新しい要素を追加するには、Enqueueメソッドを使用しましょう。
このメソッドは、キューの末尾に新しい要素を追加する操作を行います。
Enqueueメソッドは非常にシンプルで、追加したい要素を引数として渡すだけで、その要素がキューに追加されます。

以下のサンプルプログラムは、Queue<T>の使用方法を示しており、いくつかの整数をキューに追加し、その後、キューの内容をコンソールに表示する簡単な例です。


using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        var queue = new Queue<int>();

        // Queueに要素を追加
        queue.Enqueue(1);
        queue.Enqueue(2);
        queue.Enqueue(3);

        Console.WriteLine("Queueに追加された要素:");
        foreach (var item in queue)
        {
            Console.WriteLine(item);
        }
    }
}

このプログラムでは、まずQueue<int>のインスタンスを生成し、Enqueueメソッドを使って3つの整数(1, 2, 3)をキューに追加。
その後、foreachループを使用してキュー内の各要素を表示しています。

このようにEnqueueメソッドを使用することで、Queue内に新しい要素を効率的に追加し、順序を保ったままデータを管理することができます。

Queueから最も古い要素を取得して削除する(Dequeue)

Queueの中核的な機能の一つに、最も古い要素を取得して削除するDequeueメソッドがあります。
この操作は、キューの先頭にある要素、つまり最初に追加された要素を取り出し、同時にその要素をキューから削除します。
これは先入れ先出し(FIFO)の原則に基づいており、キューの基本的な動作原理を体現していますね。

以下に、Dequeueメソッドを使用したサンプルプログラムを示します。
このプログラムでは、まずいくつかの整数をキューに追加し、その後Dequeueメソッドを呼び出して、最も古い要素を取り出しています。


using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        var queue = new Queue<int>();

        // Queueに要素を追加
        queue.Enqueue(1);
        queue.Enqueue(2);
        queue.Enqueue(3);

        Console.WriteLine("Dequeue操作前のQueue:");
        foreach (var item in queue)
        {
            Console.WriteLine(item);
        }

        // Queueから要素を取得して削除
        var removedItem = queue.Dequeue();

        Console.WriteLine($"\nDequeue操作で取り出された要素: {removedItem}");
        Console.WriteLine("\nDequeue操作後のQueue:");
        foreach (var item in queue)
        {
            Console.WriteLine(item);
        }
    }
}

このプログラムでは、Enqueueメソッドを使ってキューに3つの整数を追加した後、Dequeueメソッドを呼び出して最も古い要素(この場合は1)を取り出しています。
Dequeueメソッドは、取り出された要素を返すので、その値を変数removedItemに格納。
その後、キューの内容を再度表示することで、Dequeue操作によって要素がキューから削除されたことを確認できます。

このようにDequeueメソッドを活用することで、キューの先頭にある要素に対して効率的にアクセスし、それを削除することができます。
これは、特定のタスクを順番に処理するようなシナリオで非常に有効です。

Queueの先頭の要素を削除せずに取得する(Peek)

Queueクラスには、キューの先頭にある要素を削除せずに参照するためのPeekメソッドが用意されています。
このメソッドは、キューから要素を削除することなく、どの要素が次に取り出されるかを確認するのに便利です。

以下のサンプルプログラムでは、Peekメソッドを使用してキューの先頭の要素を取得し、それを表示しています。


using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        var queue = new Queue<int>();

        // Queueに要素を追加
        queue.Enqueue(1);
        queue.Enqueue(2);
        queue.Enqueue(3);

        Console.WriteLine("Queueの現在の要素:");
        foreach (var item in queue)
        {
            Console.WriteLine(item);
        }

        // Queueの先頭の要素を削除せずに取得
        var firstItem = queue.Peek();

        Console.WriteLine($"\nPeek操作で取得された要素: {firstItem}");
        Console.WriteLine("\nPeek操作後のQueue:");
        foreach (var item in queue)
        {
            Console.WriteLine(item);
        }
    }
}

このプログラムでは、Enqueueメソッドでキューに3つの整数を追加した後、Peekメソッドを呼び出してキューの先頭にある要素を取得しています。
この場合、Peekメソッドはキューから要素を削除しませんので、キューの状態はPeekメソッド呼び出し前後で変わらないことが確認できます。

Peekメソッドは、キューの状態を変更せずに次に処理されるべき要素を調べたい場合に非常に便利です。
たとえば、複数のタスクをキューに入れて処理するプログラムでは、実際にタスクを開始する前に、どのタスクが次に来るのかをPeekで確認することができます。

Queueからすべての要素を削除する(Clear)

Queueクラスを使用する際、場合によってはキュー内のすべての要素を一度に削除したいシチュエーションがあります。
このような場合にはClearメソッドが便利です。
Clearメソッドを呼び出すことで、Queue内の全ての要素が削除され、キューの長さが0にリセットされます。

以下のサンプルプログラムは、Queueにいくつかの要素を追加した後でClearメソッドを使用してすべての要素を削除し、その結果を確認するものです。


using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        var queue = new Queue<int>();

        // Queueに要素を追加
        queue.Enqueue(1);
        queue.Enqueue(2);
        queue.Enqueue(3);

        Console.WriteLine("Clear操作前のQueueの要素数: " + queue.Count);

        // Queueの要素をすべて削除
        queue.Clear();

        Console.WriteLine("Clear操作後のQueueの要素数: " + queue.Count);
    }
}

このプログラムでは、最初にEnqueueメソッドでキューに3つの整数を追加します。
その後、Clearメソッドを呼び出してキューから全ての要素を削除し、Countプロパティを使用してキューの要素数が0になったことを確認しています。

Clearメソッドは、キューを再利用したいが中身は全て破棄したい場合や、プログラムの特定の処理段階でキューをリセットしたい場合に特に役立つでしょう。
状態を明確に管理する必要がある場合にも、Clearメソッドを適切に使うことで、エラーの原因となる古いデータが残らないようにすることができます。

Queueはどういったときに使えるか

Queue(キュー)は、データを一時的に保持し、後で順番に処理する必要がある多くのプログラミングシナリオで非常に役立ちます。
その性質上、「先入れ先出し」(FIFO: First In, First Out)の原則に基づいて動作するため、処理の順序が重要な場合に特に有用です。

以下は、Queueが役立つ具体的なシナリオの例です。

  1. タスクスケジューリングと管理
  2. オペレーティングシステムやアプリケーションでは、複数のタスクを管理し、それぞれを適切な順序で実行する必要があります。
    例えば、印刷ジョブのキューイングやバックグラウンドでのデータ処理タスクなどがこれにあたります。

  3. ウェブサーバーのリクエスト処理
  4. ウェブサーバーは同時に多くのリクエストを受け取りますが、これらを効率的に処理するためにリクエストをキューに追加し、順番に処理することがあります。

  5. リアルタイムシステムのイベント処理
  6. リアルタイムシステムでは、イベントを迅速にかつ確実に処理する必要があります。
    イベントをキューに追加し、それぞれを順に処理することで、イベントの処理順序を保証することができます。

  7. データストリームのバッファリング
  8. ストリーミングデータを扱うアプリケーションでは、データのバッファリングにキューを使用することがあります。
    これにより、データが連続して処理されることを保証し、バーストトラフィックやデータの不規則な到着に対応できます。

  9. 呼び出しのシーケンス管理
  10. プログラム内で特定の操作を一定の順序で実行する必要がある場合、その操作の呼び出しをキューに格納しておくことで、正しい順序で実行を保証することができます。

これらのシナリオは、Queueがプログラムの様々な部分でどのように役立つかを示す一例です。
Queueの利用は、プログラムの複雑性を低減し、コードの可読性と保守性を向上させるための強力なツールとなり得ます。

Queueで作るプリンターサンプルプログラム

Queueを使用して、プリンターの印刷ジョブを管理するシンプルなサンプルプログラムを考えてみましょう。
プリンターは一度に一つのジョブしか処理できないため、送信された印刷ジョブをキューで管理し、順番に処理するのが効率的です。

このサンプルでは、ユーザーからの印刷要求を模擬的にQueueに追加し、キューからジョブを取り出して「印刷」するプロセスを示します。


using System;
using System.Collections.Generic;
using System.Threading;

class PrinterJob
{
    public string DocumentName { get; set; }
    public int NumberOfPages { get; set; }

    public PrinterJob(string docName, int numPages)
    {
        DocumentName = docName;
        NumberOfPages = numPages;
    }
}

class Program
{
    static void Main()
    {
        var printQueue = new Queue<PrinterJob>();

        // 印刷ジョブをQueueに追加
        printQueue.Enqueue(new PrinterJob("Document1.pdf", 10));
        printQueue.Enqueue(new PrinterJob("Document2.pdf", 5));
        printQueue.Enqueue(new PrinterJob("Document3.pdf", 12));

        while (printQueue.Count > 0)
        {
            var job = printQueue.Dequeue();  // キューからジョブを取り出す
            Console.WriteLine($"{job.DocumentName}を印刷中... {job.NumberOfPages}ページ");

            // 印刷にかかる時間をシミュレート
            Thread.Sleep(job.NumberOfPages * 100);

            Console.WriteLine($"{job.DocumentName}の印刷が完了しました");
        }

        Console.WriteLine("すべての印刷ジョブが完了しました");
    }
}

このプログラムでは、まずPrinterJobクラスを定義して、印刷ジョブを表現しています。
Mainメソッド内では、PrinterJobのインスタンスを作成し、それらをprintQueueに追加。
その後、キューが空になるまでループを続け、キューからジョブを取り出して「印刷」し、完了メッセージを表示しています。

このサンプルは、実際のプリンターが印刷ジョブをどのように処理するかの簡単な模倣であり、Queueの利用が実際のアプリケーションでどのように役立つかを示す良い例です。
キューを使うことで、ジョブが順番にかつ効率的に処理されることが保証されます。

キャリア形成/給与還元
ひとつひとつ真摯に向き合う企業
ONE_WEDGE社員募集

株式会社 ONE WEDGEでは、新たな仲間を募集しています!

私たちと一緒に、革新的で充実したキャリアを築きませんか?
当社は、従業員が仕事と私生活のバランスを大切にできるよう、充実した福利厚生を整えています。

  • 完全週休2日制(土日休み)で、祝日や夏季休暇、年末年始休暇もしっかり保証!
  • 様々な休暇制度(有給、慶弔、産前・産後、育児、バースデー休暇)を完備!
  • 従業員の成長と健康を支援するための表彰制度、資格取得支援、健康促進手当など!
  • 生活を支えるテレワーク手当、記事寄稿手当、結婚祝金・出産祝金など、様々な手当を提供!
  • 自己啓発としての書籍購入制度や、メンバー間のコミュニケーションを深める交流費補助!
  • 成果に応じた決算賞与や、リファラル採用手当、AI手当など、頑張りをしっかり評価!
  • ワークライフバランスを重視し、副業もOK!

株式会社 ONE WEDGEでは、一人ひとりの従業員が自己実現できる環境を大切にしています。
共に成長し、刺激を与え合える仲間をお待ちしております。
あなたの能力と熱意を、ぜひ当社で発揮してください。
ご応募お待ちしております!

ホームページ、採用情報は下記ボタンからご確認ください!

応募、ご質問など、LINEでお気軽にご相談ください♪

まとめ

この記事を通じて、C#でのQueue(キュー)の基本的な使い方と、それが実際のプログラミングシナリオでどのように役立つかについて見てきました。
Queueは「先入れ先出し」(FIFO: First In, First Out) の原則に基づくデータ構造であり、データの順序を保持しながら効率的に処理を行う必要がある場合に特に有用です。

Queueの基本操作には、要素の追加(Enqueue)、最も古い要素の取得および削除(Dequeue)、先頭要素の参照(Peek)、そしてQueueの全要素のクリア(Clear)があります。
これらの操作を使いこなすことで、タスクのスケジューリング、イベント処理、データのバッファリングなど、多岐にわたるプログラムのニーズに対応することができます。

Queueは、シンプルながらも非常に強力なデータ構造です。
その機能を適切に利用することで、プログラムの効率性、可読性、そして保守性を向上させることができます。
C#でのプログラミングにおいて、Queueはデータを順序付けて処理する必要がある多くの場面でその価値を発揮します。
今回学んだ内容を活かして、実際のプログラミングプロジェクトでQueueの強力な機能を利用してみてください。

COMMENT

メールアドレスが公開されることはありません。 が付いている欄は必須項目です