当前位置: 首页 > 面试题库 >

如何在Go中实现队列?

葛炯
2023-03-14
问题内容

当前的Go库不提供队列容器。为了实现一个简单的队列,我使用圆形数组作为基础数据结构。它遵循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.

以下是代码:

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

但是输出显然是错误的:

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

11是12是0错误0错误0错误0错误0错误0错误0错误0错误0错误0错误0错误0错误

我认为我还需要一个领域来使代码正常工作。你有什么建议?

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

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

问题答案:

Enqueue失败时,您 仍在 增加p.tail,因此下一次它似乎不会失败-
这就解释了false第一个循环中的单曲(并弄乱了第二个循环中的所有内容)。原始算法说的OVERFLOW意思是“放弃一切”,而不是“只是继续前进,就好像什么都没发生一样”
;-)。

您需要做的就是p.tail如果已检查是否发生了故障,则递减-或将增加的值放在本地临时文件中,然后p.tail仅在
发生故障时才将其移动到,这可能会更优雅。这样一来,否则Enqueue不会 排队新的价值,但本身队列(而没有溢出值)仍是语义完整和正确的未来运营。



 类似资料:
  • 问题内容: 在JavaScript中实现堆栈和队列的最佳方法是什么? 我正在寻找shunting-yard算法,并且我将需要这些数据结构。 问题答案: var stack = []; stack.push(2); // stack is now [2] stack.push(5); // stack is now [2, 5] var i = stack.pop(); // stack is no

  • 问题内容: 如何在Go中实现抽象类?由于Go不允许我们在接口中包含字段,因此这将是一个无状态的对象。因此,换句话说,Go中的方法是否可以具有某种默认实现? 考虑一个例子: 由于无法将接口用作接收器,因此无法编译。 实际上,我已经回答了我的问题(请参见下面的答案)。但是,这是实现这种逻辑的惯用方式吗?除了语言的简单性之外,还有什么理由不使用默认实现吗? 问题答案: 一个简单的解决方案是移至参数列表(

  • 本文向大家介绍kafka如何实现延迟队列?相关面试题,主要包含被问及kafka如何实现延迟队列?时的应答技巧和注意事项,需要的朋友参考一下 Kafka并没有使用JDK自带的Timer或者DelayQueue来实现延迟的功能,而是基于时间轮自定义了一个用于实现延迟功能的定时器(SystemTimer)。JDK的Timer和DelayQueue插入和删除操作的平均时间复杂度为O(nlog(n)),并不

  • 问题描述 (Problem Description) 如何实现队列? 解决方案 (Solution) 以下示例显示了如何在员工结构中实现队列。 import java.util.LinkedList; class GenQueue<E> { private LinkedList<E> list = new LinkedList<E>(); public void enqueue(E i

  • 本文向大家介绍C ++程序在STL中实现队列,包括了C ++程序在STL中实现队列的使用技巧和注意事项,需要的朋友参考一下 队列是遵循先进先出(FIFO)顺序的线性结构,在该顺序中,对队列的元素执行操作。 算法 范例程式码 输出结果

  • 本文向大家介绍如何使用JavaScript实现栈与队列,包括了如何使用JavaScript实现栈与队列的使用技巧和注意事项,需要的朋友参考一下 前言 栈和队列是web开发中最常用的两种数据结构。绝大多数用户,甚至包括web开发人员,都不知道这个惊人的事实。如果你是一个程序员,那么请听我讲两个启发性的例子:使用堆栈来组织数据,来实现文本编辑器的“撤消”操作;使用队列处理数据,实现web浏览器的事件循