我想请一些关于Go指针接收器如何工作的帮助。
我在下面有一个二进制搜索树的例子,希望能帮我解释一下。
package main
import "fmt"
type Node struct {
key int
left, right *Node
}
func NewNode(key int) *Node {
return &Node{key, nil, nil}
}
type BST struct {
root *Node
}
func NewBinarySearchTree() *BST {
return &BST{nil}
}
func (t *BST) Insert(key int) {
if t.root == nil {
t.root = NewNode(key)
return
}
var node = t.root
for {
if key < node.key {
if node.left == nil {
node.left = NewNode(key)
return
} else {
node = node.left
}
} else {
if node.right == nil {
node.right = NewNode(key)
return
} else {
node = node.right
}
}
}
}
func inorder(node *Node) {
if node == nil {
return
}
inorder(node.left)
fmt.Print(node.key, " ")
inorder(node.right)
}
func main() {
tree := NewBinarySearchTree()
tree.Insert(3)
tree.Insert(1)
tree.Insert(2)
tree.Insert(4)
inorder(tree.root) // 1 2 3 4
}
然而,在我写完之后,我想我可以简化我的插入功能,如下所示:
func (t *BST) Insert2(key int) {
var node *Node
node = t.root
for node != nil {
if key < node.key {
node = node.left
} else {
node = node.right
}
}
node = NewNode(key)
}
但是,这样做,树永远不会更新。 我的想法是......
node = NewNode(key)
与t.root =
NewNode(key)
我的Insert2方法在哪里出错?有没有办法可以调整?
答案 0 :(得分:3)
node = NewNode(key)
该行不会更改树。该行更改了局部变量node
;在此行之后,node
指向不同的节点,但它用于指向的对象不受影响。要插入树中,您必须分配到t.root
,node.left
或node.right
。
答案 1 :(得分:3)
您似乎对指针的使用感到困惑。
执行node = t.root
后,您只需将node
指向t.root
点即可。
稍后,当您执行node = NewNode(key)
时,您会node
指向新创建的项目,这不是您想要的;你想让t.root
指向那个新项目。
由于您打算修改类型为*Node
(root
,left
和right
)的变量,我们需要一个指向它们的指针,因此需要一个类型的变量**Node
,还有一个间接层。
您可以先将node
指向t.root
,node := &t.root
的地址,然后继续循环播放。
您可以尝试以下内容:
func (t *BST) Insert3(key int) {
node := &t.root
for *node != nil {
if key < (*node).key {
node = &(*node).left
} else {
node = &(*node).right
}
}
*node = NewNode(key)
}
注意我们在检查循环上的地址时使用间接操作符*
来访问引用的数据,以及密钥。
在函数的最后,*node = NewNode(key)
执行您最初打算执行的操作;您将新创建的项目分配给根,左或右指针。