如何在Go中实现队列? [英] How to implement a queue in Go?

查看:169
本文介绍了如何在Go中实现队列?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当前的Go库不提供队列容器。
为了实现一个简单的队列,我使用圆阵列作为基础数据结构。
它遵循TAOCP中提到的算法:

 将Y插入队列X:X [R] <-Y; R< ;-( R + 1)%M;如果R = F,则溢出。 
从队列X中删除Y:如果F = R,则UNDERFLOW; Y'LT; -X [F]; F < - (F + 1)%M
F:前,R:后,M:数组长度。

以下是代码:

<$ p $ (b











$
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 {
pq [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:= pq [p.head]
p.head =(p.head + 1)%p.len
return x,true
}

func main(){
q:= New (10)
for i:= 1;我< 13; i ++ {
fmt.Println(i,q.Enqueue(i))
}
fmt.Println()
for i:= 1;我< 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 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



我想我需要一个字段使代码正常工作。
您有什么建议?

改进后的代码有一个小缺点:一个大小为n的数组只能包含n-1个元素。

 包裹主要

进口(
fmt


类型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 {
pq [p.tail] = x
ntail:=(p.tail + 1)%p.len
ok:= false
如果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:= pq [p.head]
p.head = (p.head + 1)%p.len
return x,true
}

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


Enqueue 失败时,您仍然 递增 p.tail ,所以下次它看起来不会失败 - 这就解释了第一个循环中的单个 false 第二个)。原始的算法是 OVERFLOW ,意思是放弃所有东西,而不是只要继续下去,就好像没有任何不良事件发生一样; - )。



如果您检查了发生的故障,或者将增加后的值放入本地临时文件并移动它,您只需减少 p.tail p.tail ,只有当 时,才会更优雅。这样,失败的 Enqueue 不会排列新值,但是队列本身(没有溢出值)仍然在语义上保持完好并且正确未来的行动。


The current Go library doesn't provide the queue container. To implement a simple queue, I use circle array as the underlying data structure. It follows algorithms mentioned in TAOCP:

Insert Y into queue X: X[R]<-Y; R<-(R+1)%M; if R=F then OVERFLOW.
Delete Y from queue X: if F=R then UNDERFLOW; Y<-X[F]; F<-(F+1) % M.
F: Front, R: Rear, M: Array length.

Following is the code:

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

But the output is obviously wrong:

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

I think I need one more field to make the code work properly. What do you suggest?

The improved code has a small shortcoming: an array of size n can contain only n-1 elements.

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

解决方案

When Enqueue fails, you're still incrementing p.tail, so next time it will appear not to fail -- that explains the single false in your first loop (and messes everything up for the second one). The original algorithm says OVERFLOW meaning "give everything up", not "just keep going as if nothing untowards happened";-).

All you need to do is decrement p.tail if you've checked that failure's occurring -- or put the incremented value in a local temporary and move it to p.tail only if failure is not occurring, that may be more elegant. This way, the failing Enqueue does not enqueue the new value, but the queue itself (without that overflowing value) is still semantically intact and correct for future operations.

这篇关于如何在Go中实现队列?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆