1 回答
TA贡献1796条经验 获得超7个赞
指针是值,就像int数字一样。不同之处在于对该值的解释:指针被解释为内存地址,而ints 被解释为整数。
当要改变类型的变量的值int,则通过一个指向int它的类型的*int,并且修改尖锐的物体:*i = newvalue(分配值是一个int)。
指针也一样:当你想改变一个指针类型的变量的值时*int,你传递一个指向该*int类型的指针**int并修改指向的对象:(*i = &newvalue分配的值是一个*int)。
传递指针是必需的,因为副本是由您传递的所有内容制成的,您只能修改副本。当你传递一个指针,同样的事情发生了:一个副本也取得了该指针的,但我们不修改该指针本身,而是尖锐的价值。
您要修改类型为 的变量*AvlTree。在 Go 中,接收者不能是指向指针的指针。规范:方法声明:
接收者的类型必须是格式T或*T(可能使用括号) whereT是类型名称。表示的类型T称为接收器基类型;它不能是指针或接口类型,并且必须在与方法相同的包中声明。
所以你有2个选择:
要么编写一个简单的函数(不是方法),它接受 a**AvlTree并且您可以传递树指针的地址,因此该函数可以修改树指针(指向的对象)
或从您的函数/方法返回树指针,并让调用者将其分配给作为树指针的变量。
解决您对返回树指针的担忧:这没有错。看看内置函数append():它将元素附加到切片并返回修改后的切片。您(调用者)必须将返回的切片分配给切片变量,因为append()如果附加元素不适合原始元素,则可能会通过分配新切片来修改切片(并且由于append()采用非指针,修改后的值必须是回)。
以下是 #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
}
为了轻松检查结果,我实现了一些方法来生成string表示:
func (tree *AvlTree) String() string { return tree.str(1) }
func (tree *AvlTree) str(n int) string {
if tree == nil {
return "<nil>"
}
return fmt.Sprintf("%q\n%s%v,%v\n%s", tree.value, strings.Repeat("\t", n),
tree.left.str(n+1), tree.right.str(n+1), strings.Repeat("\t", 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>,<nil>
,"R"
<nil>,<nil>
和转换后的树(正是你想要的):
"L"
"LL"
<nil>,<nil>
,"t"
"LR"
<nil>,<nil>
,"R"
<nil>,<nil>
- 1 回答
- 0 关注
- 168 浏览
添加回答
举报