【发布时间】:2016-05-27 01:53:52
【问题描述】:
我一直在研究 Golang,并一直在实现一些数据结构来了解该语言的工作原理。我在编写 AVL 树的代码时遇到了以下问题:
从结构指针方法分配主指针似乎在函数范围之外没有任何影响。例如。 tree.rotateLeftToRoot() 不会导致 tree.left 成为新树。
问题: 有没有办法在 Golang 的结构指针方法中重新分配指针,或者这通常是不鼓励的?在示例中,这将是 "tree = prevLeft" 行。
代码sn-p:
//Graphical representation of t.rotateLeftToRoot():
// t L
// L R -> LL t
//LL LR LR R
func (tree *AvlTree) rotateLeftToRoot() {
if tree == nil {
return
}
prevLeft := tree.left
if prevLeft != nil {
tree.left = prevLeft.right //tree.left passed root its right branch
prevLeft.right = tree //tree becomes tree.left's right branch
tree.updateHeight()
prevLeft.updateHeight()
tree = prevLeft //desired behaviour: tree.left becomes the new tree
//actual behaviour: no effect when function returns
}
}
我尝试了其他设置树的值或地址的组合,但都没有达到预期的效果。例如,*tree = *prevLeft 会导致无限循环。
附加说明:返回tree 并设置"tree = tree.rotateLeftToRoot()" 可以避免该问题。这可行,但是当调用者真的只想能够调用函数来更新树时,混合效果并要求分配返回值似乎很脏。
可以在函数中将tree 设置为prevLeft 吗?
【问题讨论】:
-
如果你想修改别人持有的
tree *,你需要编写一个函数来接收(或接收)tree **。为了修改一个指针,你需要一个指向它的指针。 -
我会让它返回更新后的
*AvlTree。或者,你可以改变你的类型定义,所以你现在称之为AvlTree的东西被命名为Node(或者node,如果你不想公开它)并定义type AvlTree *Node,所以@上的一个方法987654337@可以改变节点指针。 (这将像@hobbs 所说的那样执行,只是名称不同。)使用指针到指针可能会导致更多的分配和更多的指针追逐,但可能还不够关心。跨度> -
@hobbs 感谢您的建议。我尝试将树** 传递给函数,它似乎有完全相同的问题。有没有我错过的步骤?
func rotateLeftToRoot(ptrToTreePtr **AvlTree) { ... tree := *ptrToTreePtr /*manipulations on tree, tree = prevLeft*/ *ptrToTreePtr = tree }一旦函数返回,树就指向原来的节点而不是prevLeft。 -
我再次尝试更新测试,本地函数 rotateLeft(ptree **AvlTree) 成功运行。感谢 hobbs 和 twotwotwo 的建议。