キューとは
尾 要素を所定の順序で格納および取得するために使用されるデータ構造です。スタックに似た線形データ構造であり、 FIFO (先入れ先出し) ルール。これは、順番待ちリストや、最初に到着した人が最初にサービスを受ける列と比較される場合があります。既存のコンポーネントは、 列 、そして新しい要素が背面に追加されます。
Golang でのキューの実装
の実装 列 in Go はシンプルかつ効率的で、次の 4 つの方法を使用して実装できます。
1: スライス
囲碁では、 スライス サイズを変更できる動的配列です。実装するには 列 を使って スライス の後ろに要素を追加できます スライス 組み込みの追加機能を使用して、先頭から要素を削除します スライス スライスを使用。
このアプローチは簡単に構築でき、Go の組み込みスライスにより、追加操作とスライス操作のパフォーマンスが向上します。ただし、新しい基本配列への要素のコピーを含むスライス方法は、次の場合に非効率になる可能性があります。 列 展開し、デキュー操作を繰り返す必要があります。
次のコードは、 列 Goでスライスを使った実装。
パッケージメイン
輸入 'fmt'
関数メイン ( ) {
列 := 作る ( [ ] インターフェース { } 、 0 )
列 = 追加 ( 列 、 '英語' )
列 = 追加 ( 列 、 「ウルドゥー語」 )
列 = 追加 ( 列 、 「数学」 )
もしも それだけ ( 列 ) > 0 {
アイテム := 列 [ 0 ]
列 = 列 [ 1 : ]
fmt。 プリントイン ( アイテム )
}
もしも それだけ ( 列 ) == 0 {
fmt。 プリントイン ( 「キューは空です」 )
} それ以外 {
fmt。 プリントイン ( 列 )
}
}
上記の Go コードは、スライスを使用して簡単な 列 データ構造。の 追加() 関数は、要素をキューに入れるために使用されます 列 最初の要素を削除するスライス操作を使用して、それらをデキューします。と fmt.Println() 、デキューされた要素が出力されます。次に、コードは それだけ() 関数は、キューが空かどうかを判断し、空である場合は「 列 fmt.Println() 関数を使用して空です」。
出力
2: リンクされたリスト
値と、リスト内の次のノードへのポインターを持つノードは、リンクされたリストを構成します。 1 つはリストの先頭 (頭) を指し、もう 1 つは後 (末尾) を指す 2 つのポインターを使用して、 列 リンクされたリストを使用します。キューからアイテムを削除する (デキュー) には、リストの先頭にあるノードを削除する必要があり、キューにアイテムを追加する (エンキュー) には、リストの最後に新しいノードを追加する必要があります。
この方法では、要素をコピーする必要があるスライスベースのソリューションとは対照的に、変更する必要があるのはヘッド ポインターとテール ポインターのみであるため、効率的なエンキュー操作とデキュー操作が可能になります。
リンクされたリストを使用して実装します 列 以下の提供されたコードを使用して:
パッケージメイン輸入 'fmt'
タイプノード 構造体 {
値インターフェイス { }
次 * ノード
}
タイプキュー 構造体 {
頭 * ノード
しっぽ * ノード
}
関数メイン ( ) {
列 := & 列 { 頭 : なし 、 しっぽ : なし }
新しいノード := & ノード { 価値 : '英語' 、 次 : なし }
列。 しっぽ = 新しいノード
列。 頭 = 新しいノード
新しいノード = & ノード { 価値 : 「ウルドゥー語」 、 次 : なし }
列。 しっぽ . 次 = 新しいノード
列。 しっぽ = 新しいノード
新しいノード = & ノード { 価値 : 「数学」 、 次 : なし }
列。 しっぽ . 次 = 新しいノード
列。 しっぽ = 新しいノード
もしも 列。 頭 != なし {
アイテム := 列。 頭 . 価値
列。 頭 = 列。 頭 . 次
fmt。 プリントイン ( アイテム )
}
もしも 列。 頭 == なし {
fmt。 プリントイン ( 「キューは空です」 )
}
}
Node 構造体は、キュー内の各アイテムを表し、アイテムの値を格納するための value フィールドと、キュー内の次のアイテムを指すための next フィールドの 2 つのフィールドを含みます。 Queue 構造体は head プロパティと tail プロパティを使用して、キューの前後をそれぞれ追跡します。の しっぽの 最初の項目は head プロパティで示され、最後の項目は tail プロパティで示されます。
head と tail のパラメーターは、最初は次のように設定されています。 なし 新しいとき 列 main() 関数で確立されます。ヘッド ポインタとテール ポインタが更新され、3 つのノードが 列 値で 「英語」、「ウルドゥー語」、 と 「数学」。 の '英語' アイテムはその後 「デキュー」 (削除) の前面から 列 その値を表示し、ヘッド ポインタを次のノードに進めます。 列 .デキュー後、head が null になった場合は、キューが空であることを意味し、「 列 空です」と印字されます。
出力
3: 構造物
Go では、と呼ばれるカスタム データ構造を作成できます。 構造体 を表す 列 .これ 構造体 を格納するフィールドを持つことができます 列 アイテムを追加および削除し、キューが空かどうかを確認し、現在のキュー サイズを取得するための要素とメソッド。
この作成方法 列 in Go は、より多くの機能で拡張およびカスタマイズできる使いやすいメソッドを備えた、便利でカプセル化された実装を提供します。これは、必要に応じて実装を変更したり、新しい機能を追加したりできる柔軟なアプローチです。
カスタムの作成 構造体 メソッドを使用する方法は、他の 2 つの方法に比べて追加のコードを記述する必要があるため、複雑さが増す可能性があります。ただし、実装の柔軟性と制御も向上します。 列 .
次の例は、を表すデータ構造の作成を示しています。 列 囲碁で。
パッケージメイン輸入 'fmt'
タイプキュー 構造体 {
アイテム [ ] インターフェース { }
}
機能 ( q * 列 ) エンキュー ( アイテムインターフェース { } ) {
q. アイテム = 追加 ( q. アイテム 、 アイテム )
}
機能 ( q * 列 ) デキュー ( ) インターフェース { } {
もしも それだけ ( q. アイテム ) == 0 {
戻る なし
}
アイテム := q. アイテム [ 0 ]
q. アイテム = q. アイテム [ 1 : ]
戻る アイテム
}
機能 ( q * 列 ) 空です ( ) ブール {
戻る それだけ ( q. アイテム ) == 0
}
機能 ( q * 列 ) サイズ ( ) 整数 {
戻る それだけ ( q. アイテム )
}
関数メイン ( ) {
列 := & 列 { アイテム : 作る ( [ ] インターフェース { } 、 0 ) }
列。 エンキュー ( '英語' )
列。 エンキュー ( 「ウルドゥー語」 )
列。 エンキュー ( 「数学」 )
アイテム := 列。 デキュー ( )
fmt。 プリントイン ( アイテム )
もしも 列。 空です ( ) {
fmt。 プリントイン ( 「キューは空です」 )
}
サイズ := 列。 サイズ ( )
fmt。 プリントイン ( 「キューのサイズ:」 、 サイズ )
}
上記のコードでは、アイテムはアイテムのスライスに追加されます。 エンキュー() メソッドの最後に移動します。 列 .に続いて 先入れ先出し (FIFO) 原則、 デキュー() メソッドは、オブジェクトの前面からアイテムを取り出します 列 そしてそれを返します。アイテムのスライスの長さは、 IsEmpty() メソッドのチェックで 列 空です。アイテム スライスの長さを返すことにより、 サイズ() メソッドは現在の しっぽの サイズ。
main() 関数は、 キュー構造体 新しいものを作成する 列 、それに要素を追加し、そこから項目を削除し、 列 は空で、そのサイズを計算します。
出力
4: チャネル
Go では、組み込みのチャネル タイプを使用して、 列 データ構造。任意の時点でエンキューできる要素の数を制限するバッファ サイズを使用してチャネルを作成できます。に要素を追加するには 列 を使用してチャネルに送信できます。 <- 演算子、キューから要素を削除する間、同じ演算子を使用してチャネルから受け取ることができます。
このアプローチは、 列 チャネルは本質的に同時使用に対して安全であるため、必須です。
Go チャネルは型付けされていることを覚えておくことが重要です。これは、チャネルを介して特定の型の値のみを送信でき、チャネルから同じ型の値のみを受信できることを意味します。
これは、チャネルを使用して 列 Go のデータ構造。
パッケージメイン輸入 (
'fmt'
'時間'
)
タイプキュー 構造体 {
アイテムチャンネルインターフェース { }
}
funcNewQueue ( ) * 列 {
q := & 列 {
アイテム : 作る ( ちゃんインターフェース { } ) 、
}
qに行きます。 プロセスアイテム ( )
戻る q
}
機能 ( q * 列 ) プロセスアイテム ( ) {
ために アイテム := 範囲q。 アイテム {
もしも アイテム == '英語' {
fmt。 プリントイン ( 「デキュー:」 、 アイテム )
}
}
}
機能 ( q * 列 ) エンキュー ( アイテムインターフェース { } ) {
q. アイテム <- アイテム
}
機能メイン ( ) {
列 := NewQueue ( )
列。 エンキュー ( '英語' )
列。 エンキュー ( 「ウルドゥー語」 )
列。 エンキュー ( 「数学」 )
時間 . 寝る ( 2 * 時間 . 2番 )
}
上記のコードは、 キュー構造体 単一のフィールドで アイテム のチャンネルです インターフェース{} タイプ。の NewQueue() 関数は、の新しいインスタンスを作成します 列 そしてその初期化 「アイテム」 新しいバッファリングされていないチャネルを持つフィールド。また、新しいゴルーチンを開始して、キューに追加されたアイテムを処理します。 プロセスアイテム() 関数。の プロセスアイテム() 関数は、受け取ったアイテムが等しいかどうかをチェックします '英語' そのアイテムのみのメッセージをコンソールに出力します。の エンキュー() 関数を使用して、新しいアイテムをキューに追加します。
出力
結論
キューは、要素を特定の順序で格納および取得するために使用される Go の重要なデータ構造です。の実装 列 in Go はスレッドセーフであるため、プログラムに並行性を実装するための理想的な選択肢となっています。スライス、連結リスト、構造、およびチャネルを使用して実装できます。完全な詳細は、上記のガイドラインで既に提供されています。