【问题标题】:Why does my Go pointer receiver not cause an update?为什么我的 Go 指针接收器不会导致更新?
【发布时间】:2013-11-07 17:00:16
【问题描述】:

我想要一些关于 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)
}

但是,以这种方式执行此操作,树永远不会更新。 我的想法是……

  • 在第一次插入时,根节点将为 nil。
  • 所以引用 t.root 的局部变量节点也将为 nil
  • 因此将跳过 for 循环。
  • node = NewNode(key) 将具有与 t.root = NewNode(key) 相同的效果

我的 Insert2 方法哪里出错了?有什么办法可以调整吗?

【问题讨论】:

    标签: go


    【解决方案1】:

    您似乎对指针的用法感到困惑。

    当你做node = t.root 时,你只是让node 指向t.root 指向的任何东西。

    稍后,当您执行node = NewNode(key) 时,您使node 指向一个新创建的项目,这不是您想要的;你想让t.root 指向那个新项目。

    由于您打算修改 *Node 类型的变量(rootleftright),我们需要一个指向它们的指针,因此需要一个 **Node 类型的变量,多一层间接的。

    你可以先让node指向t.root的地址,node := &amp;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)
    }
    

    注意我们使用间接操作符*来访问引用的数据,在检查循环上的地址时,也是key。

    在函数的最后,*node = NewNode(key) 做了你原本打算做的事情;您正在将新创建的项目分配给根、左或右指针。

    【讨论】:

      【解决方案2】:
      node = NewNode(key)
      

      那条线不会改变树。该行更改了局部变量node;在这一行之后,node 指向不同的节点,但它曾经指向的对象不受影响。要插入到树中,您必须分配给t.rootnode.leftnode.right

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-12-18
        • 2014-01-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-07-23
        • 2021-10-25
        • 2015-08-04
        相关资源
        最近更新 更多