我开始学习围棋,但我无法弄清楚该主题的某些内容。这是链接列表
type List struct {
next *List
val any
}
我创建一个这样的实例
myList := &List{nil, 1}
我添加更多链接并尝试像这样部署它
func (n *List) Reverse() {
var tmp *List
tmp = n
var prev *List
var last *List
for tmp != nil {
last = tmp.next
tmp.next = prev
prev = tmp
tmp = last
}
*n = *prev
}
传播本身是标准的,取自另一种有效的语言。但是这里的列表奇怪地循环了。我究竟做错了什么?这个列表1 2 3 4 变成4 3 2 4 3 2 4 3 2 4 3 2 4 3 2 4 3 2 4
当您在表达式中获取列表的第一个元素时
tmp = n,您正在写入tmp指向与它指向的相同内存位置的指针n。因此,当您访问第二个元素时,它的指针
.next指向n当你在循环之后执行时
*n = *prev,会发生这种情况: 和 字段的值在地址处发生了变化,n但值本身并没有改变。这意味着反向列表的最后一个元素将指向列表的头部。结果是一个循环。n->nextn->valn为了不发生循环,当最后一个元素被访问时,它必须在一个新的位置。而是
tmp = n写tmp = &List{n.next, n.val}实际上,您的
Push工作正是因为您last := *n通过分配在堆上的新位置创建了列表头部的副本。结果,在赋值之后*n = *node,单元格n.next包含一个指向新分配的指针last工作代码示例https://go.dev/play/p/LiWA4NfpV82
添加剂
如何在不创建新节点的情况下反转列表。
n您需要交换这些对的内容,而不是仅仅复制反向列表头部的内容。并更新倒数第二个元素中的指针:完整代码https://go.dev/play/p/GCNLeGWxezi 警告:此示例不检查列表中的循环。
是的,它真的不会那样工作。好吧,至少它对我也不起作用。我认为不能直接更改接收方地址,也不能这样做:
但你可以这样做:
这看起来并不漂亮,而且可能是惯用的错误。然后,您可以将指向列表头部的指针存储在单独的结构变量中,如本例中所做的那样: https ://gist.github.com/PARUS/55ee88bfecb87f8614e1a4f67b57c866