Home >Backend Development >Golang >How to Correctly Implement a Queue Data Structure in Go Using a Circular Array?

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

Susan Sarandon
Susan SarandonOriginal
2024-11-29 06:36:10187browse

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

How to implement a queue in Go?

Background:

In Go, the standard library lacks a queue container. To implement a queue, you can utilize a circular array as the underlying data structure.

Initial Implementation:

The provided code employs a circular array with the following algorithms:

  • Insertion: Insert Y into queue X: X[R] <- Y; R <- (R 1) % M; if R = F then OVERFLOW.
  • Deletion: Delete Y from queue X: if F = R then UNDERFLOW; Y <- X[F]; F <- (F 1) % M.

Where F is the front, R is the rear, and M is the array length.

Code and Incorrect Output:

The provided code implements these algorithms, but the output exhibits incorrect 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())
    }
}
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

Solution:

To rectify this issue, an additional field is required. The modified code incorporates a check to ensure that the updated tail position does not coincide with the head:

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())
    }
}

With this correction, the output is accurate:

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

Alternative Implementation Using Slices:

In modern Go versions, a simpler implementation is possible using 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)
    }
}

This implementation leverages slices' dynamic growth and garbage collection, making it both efficient and practical.

The above is the detailed content of How to Correctly Implement a Queue Data Structure in Go Using a Circular Array?. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn