在惯用Go中设置的最小值

时间:2014-09-26 15:44:31

标签: algorithm go set idiomatic

如何编写一个返回set中最小值的函数?我不只是在寻找一个解决方案(我知道我可以在迭代第一个元素时初始化最小值,然后设置一个我初始化最小值的布尔变量),而不是惯用解决方案。由于go没有原生集,假设我们有map[Cell]bool

2 个答案:

答案 0 :(得分:2)

地图是在Go中实现集合的惯用方法。惯用代码使用bool或struct {}作为地图的值类型。后者使用较少的存储空间,但需要在键盘上输入更多内容才能使用。

假设单元格的最大值为maxCell,则此函数将计算min:

func min(m map[Cell]bool) Cell {
    min := maxCell
    for k := range m {
        if k < min {
            min = k
        }
    }
    return min
}

如果Cell是数字类型,则可以将maxCell设置为math constants之一。

使用地图的任何解决方案都需要在键上循环。

除地图外,您还可以保留heap以找到最低要求。这将需要更多的存储和代码,但可以更高效,具体取决于集合的大小以及调用最小函数的频率。

答案 1 :(得分:2)

一种不同的方法,取决于您的设置有多大,使用自我排序切片可以更有效:

type Cell uint64

type CellSet struct {
    cells []Cell
}

func (cs *CellSet) Len() int {
    return len(cs.cells)
}

func (cs *CellSet) Swap(i, j int) {
    cs.cells[i], cs.cells[j] = cs.cells[j], cs.cells[i]
}

func (cs *CellSet) Less(i, j int) bool {
    return cs.cells[i] < cs.cells[j]
}

func (cs *CellSet) Add(c Cell) {
    for _, v := range cs.cells {
        if v == c {
            return
        }
    }
    cs.cells = append(cs.cells, c)
    sort.Sort(cs)
}

func (cs *CellSet) Min() Cell {
    if cs.Len() > 0 {
        return cs.cells[0]
    }
    return 0
}

func (cs *CellSet) Max() Cell {
    if l := cs.Len(); l > 0 {
        return cs.cells[l-1]
    }
    return ^Cell(0)
}

playground //这是一个测试文件,将其复制到set_test.go并运行go test -bench=. -benchmem -v

BenchmarkSlice                20          75385089 ns/op             104 B/op          0 allocs/op
BenchmarkMap                  20          77541424 ns/op             158 B/op          0 allocs/op
BenchmarkSliceAndMin          20          77155563 ns/op             104 B/op          0 allocs/op
BenchmarkMapAndMin             1        1827782378 ns/op            2976 B/op          8 allocs/op