Maison > développement back-end > Golang > Comment implémenter correctement une structure de données de file d'attente dans Go à l'aide d'un tableau circulaire ?

Comment implémenter correctement une structure de données de file d'attente dans Go à l'aide d'un tableau circulaire ?

Susan Sarandon
Libérer: 2024-11-29 06:36:10
original
271 Les gens l'ont consulté

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

Comment implémenter une file d'attente dans Go ?

Contexte :

Dans Go, la bibliothèque standard n'a pas de conteneur de file d'attente . Pour implémenter une file d'attente, vous pouvez utiliser un tableau circulaire comme structure de données sous-jacente.

Implémentation initiale :

Le code fourni utilise un tableau circulaire avec les algorithmes suivants :

  • Insertion : Insérer Y dans la file d'attente X : X[R] <- Y; R <- (R 1) % M ; si R = F alors OVERFLOW.
  • Suppression : Supprimer Y de la file d'attente X : si F = R alors UNDERFLOW ; Y &Lt ;- X[F] ; F <- (F 1) % M.

Où F est l'avant, R est l'arrière et M est la longueur du tableau.

Code et incorrect Résultat :

Le code fourni implémente ces algorithmes, mais la sortie présente des résultats incorrects behavior:

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())
    }
}
Copier après la connexion
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
Copier après la connexion

Solution:

Pour remédier à ce problème, un champ supplémentaire est requis. Le code modifié intègre une vérification pour garantir que la position de la queue mise à jour ne coïncide pas avec la tête :

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())
    }
}
Copier après la connexion

Avec cette correction, le résultat est précis :

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
Copier après la connexion

Implémentation alternative à l'aide de Slices :

Dans les versions Go modernes, une implémentation plus simple est possible en utilisant slices :

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)
    }
}
Copier après la connexion

Cette implémentation exploite la croissance dynamique et la collecte des déchets des slices, ce qui la rend à la fois efficace et pratique.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Derniers articles par auteur
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal