指针 – Golang:结构指针方法中的指针可以重新分配给另一个实例
我一直在研究Golang并且已经实现了一些数据结构来学习语言的工作原理.在编写AVL树的代码时,我遇到了以下问题:
从结构指针方法分配主指针似乎在函数范围之外没有任何影响.例如. tree.rotateLeftToRoot()不会导致tree.left成为新树. 问题:有没有办法在Golang中的结构指针方法中重新指定指针,或者这通常是不鼓励的?在示例中,这将是“tree = prevLeft”行. 代码段: //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.rotateLeftToRoot()”可以避免此问题.这是有效的,但是当调用者真的只想调用函数来更新树时,混合效果并要求赋值给返回值似乎很脏. 可以从函数中将树设置为prevLeft吗?
指针的值就像让我们说int数字一样.不同之处在于对该值的解释:指针被解释为内存地址,而int被解释为整数.
如果要更改int类型变量的值,则将指针传递给该类型为* int的int,并修改指向的对象:* i = newvalue(赋值的值为int). 指针也是如此:当你想要改变指针类型* int的变量的值时,你传递一个指向* int的类型为**的指针,你修改了指向的对象:* i =& newvalue(分配的值是* int). 传递指针是必需的,因为复制是从您传递的所有内容制作的,并且您只能修改副本.当你传递一个指针时,同样的事情发生了:一个副本也是由那个指针构成的,但是我们不是修改指针本身而是修改指向的值. 您想要修改* AvlTree类型的变量.在Go中,接收器不能是指向指针的指针. Spec: Method declarations:
所以你有两个选择: >要么写一个简单的函数(不是方法),它需要一个** AvlTree,你可以传递树指针的地址,所以该函数可以修改树指针(指向的对象) 解决有关返回树指针的问题:这没有任何问题.看看内置函数 以下是#1的解决方案如何: func rotateLeftToRoot(ptree **AvlTree) { tree := *ptree if tree == nil { return } prevLeft := tree.left if prevLeft != nil { tree.left = prevLeft.right prevLeft.right = tree tree = prevLeft } *ptree = tree } 我已经在Go Playground上实现了它以证明它有效. 我用过这种类型: type AvlTree struct { value string left *AvlTree right *AvlTree } 为了便于检查结果,我实现了一些方法来生成字符串表示: func (tree *AvlTree) String() string { return tree.str(1) } func (tree *AvlTree) str(n int) string { if tree == nil { return "<nil>" } return fmt.Sprintf("%qn%s%v,%vn%s",tree.value,strings.Repeat("t",n),tree.left.str(n+1),tree.right.str(n+1),n-1)) } 这就是树的构建和转换方式: tree := &AvlTree{ value: "t",left: &AvlTree{ value: "L",left: &AvlTree{ value: "LL",},right: &AvlTree{ value: "LR",right: &AvlTree{ value: "R",} fmt.Println(tree) rotateLeftToRoot(&tree) fmt.Println(tree) 原始树(没有转换): "t" "L" "LL" <nil>,<nil>,"LR" <nil>,"R" <nil>,<nil> 变换后的树(正是你想要的): "L" "LL" <nil>,"t" "LR" <nil>,"R" <nil>,<nil> (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |