2 回答
TA贡献1797条经验 获得超6个赞
尝试这个练习:使用指针接收器编写所有函数。在每个函数中,获取顶部指针的当前值,直到需要更改通过指针存储的值为止。
因此,和 分别变为:SwapPush
func (p *maxHeap) Swap(a, b int) {
max := *p
max[a], max[b] = max[b], max[a]
}
func (p *maxHeap) Push(a interface{}) {
max := *p
*p = append(max, a.(int))
}
根据需要对其他函数重复上述步骤。
现在,返回每个转换后的函数。哪些人为 *p 分配了新值?哪些函数从不分配新值,而只是继续使用 max?
当你回答这个问题时,你应该发现自己开悟了。
旁注:由于立即转换为,它可能应该采取.同样,应该只是返回。或者,请参阅标准容器/堆包。PushaintintPopint
TA贡献1842条经验 获得超12个赞
原因在于,在您的情况下,切片确实是一个指针。切片由指向基础内存的指针、该内存的当前长度和总容量组成。这意味着切片实际上是具有以下三个要素的数据结构:[]int
内存指针
长度
能力
你可以把它想象成一个
type slice struct { data unsafe.Pointer length int capacity int}
现在,当您调用它时,它将切片作为输入,并返回切片作为输出。append
如果输入切片有足够的容量来添加新元素,则将其更改到位(append是一个特殊的内置函数,它不需要切片指针作为输入,无论如何它都会更改切片)。
如果输入切片没有添加新项的能力,则会创建一个具有足够容量的新切片,将旧切片复制到其中,然后在最后添加新数据。然后返回此新切片。
在您的情况下,您希望更改函数中的堆。该函数可能会返回一个新切片,您必须用它覆盖现有切片。这意味着您需要指向切片的指针,因为您要替换切片结构。Push
append
在 and 函数中,您可以更改切片的内容,而不是切片数据结构本身。您可以使用切片包含的内存指针访问切片中的数据。这意味着这些函数使用切片数据结构的副本,但切片数据结构的原始副本和副本都指向同一基础内存。切片引用的内存是相同的。由于您不在此处调用 append,因此不需要更新切片本身。Swap
Less
在函数中,您再次更改切片数据结构,因为您更改了其长度字段。这就是为什么您需要一个指向此处切片的指针。Pop
- 2 回答
- 0 关注
- 111 浏览
添加回答
举报