ホームページ >バックエンド開発 >Golang >循環配列を使用して Go でキュー データ構造を正しく実装するにはどうすればよいですか?

循環配列を使用して Go でキュー データ構造を正しく実装するにはどうすればよいですか?

Susan Sarandon
Susan Sarandonオリジナル
2024-11-29 06:36:10199ブラウズ

How to Correctly Implement a Queue Data Structure in Go Using a Circular Array?

Go でキューを実装するには?

背景:

Go では、標準ライブラリにキュー コンテナーがありません。キューを実装するには、基になるデータ構造として循環配列を利用できます。

初期実装:

提供されたコードは、次のアルゴリズムを使用して循環配列を使用します。

  • 挿入: Y をキュー X に挿入: X[R]
  • 削除: キュー X から Y を削除: F = R の場合、UNDERFLOW。 Y
ここで、F は前部、R は後部、M は配列の長さです。

コードと不正出力:

提供されたコードはこれらのアルゴリズムを実装していますが、出力は正しくありません。動作:

package main

import (
    "fmt"
)

type Queue struct {
    len        int
    head, tail int
    q          []int
}

func New(n int) *Queue {
    return &Queue{n, 0, 0, make([]int, n)}
}

func (p *Queue) Enqueue(x int) bool {
    p.q[p.tail] = x
    p.tail = (p.tail + 1) % p.len
    return p.head != p.tail
}

func (p *Queue) Dequeue() (int, bool) {
    if p.head == p.tail {
        return 0, false
    }
    x := p.q[p.head]
    p.head = (p.head + 1) % p.len
    return x, true
}

func main() {
    q := New(10)
    for i := 1; i < 13; i++ {
        fmt.Println(i, q.Enqueue(i))
    }
    fmt.Println()
    for i := 1; i < 13; i++ {
        fmt.Println(q.Dequeue())
    }
}
Output:

1 true
2 true
3 true
4 true
5 true
6 true
7 true
8 true
9 true
10 false
11 true
12 true

11 true
12 true
0 false
0 false
0 false
0 false
0 false
0 false
0 false
0 false
0 false
0 false

解決策:

この問題を修正するには、追加のフィールドが必要です。変更されたコードには、更新された末尾の位置が先頭と一致しないことを確認するチェックが組み込まれています:

package main

import (
    "fmt"
)

type Queue struct {
    len        int
    head, tail int
    q          []int
}

func New(n int) *Queue {
    return &Queue{n, 0, 0, make([]int, n)}
}

func (p *Queue) Enqueue(x int) bool {
    p.q[p.tail] = x
    ntail := (p.tail + 1) % p.len
    ok := false
    if ntail != p.head {
        p.tail = ntail
        ok = true
    }
    return ok
}

func (p *Queue) Dequeue() (int, bool) {
    if p.head == p.tail {
        return 0, false
    }
    x := p.q[p.head]
    p.head = (p.head + 1) % p.len
    return x, true
}

func main() {
    q := New(10)
    for i := 1; i < 13; i++ {
        fmt.Println(i, q.Enqueue(i))
    }
    fmt.Println()
    for i := 1; i < 13; i++ {
        fmt.Println(q.Dequeue())
    }
}
この修正により、出力は正確になります:

1 true
2 true
3 true
4 true
5 true
6 true
7 true
8 true
9 true
10 true
11 true
12 true

1
2
3
4
5
6
7
8
9
10
11
12

スライスを使用した代替実装:

最新の Go バージョンでは、次を使用してより単純な実装が可能です。スライス:

package main

import (
    "fmt"
)

// Queue implements a queue using a slice.
type Queue []int

// Enqueue adds an element to the end of the queue.
func (q *Queue) Enqueue(x int) {
    *q = append(*q, x)
}

// Dequeue removes and returns the first element of the queue.
func (q *Queue) Dequeue() (int, bool) {
    if len(*q) == 0 {
        return 0, false
    }
    x := (*q)[0]
    *q = (*q)[1:]
    return x, true
}

func main() {
    q := Queue{}
    for i := 1; i < 13; i++ {
        q.Enqueue(i)
    }
    fmt.Println(q)

    for i := 0; i < 12; i++ {
        x, _ := q.Dequeue()
        fmt.Println(x)
    }
}
この実装では、スライスの動的な拡張とガベージ コレクションを活用し、効率的かつ実用的になります。

以上が循環配列を使用して Go でキュー データ構造を正しく実装するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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