#go #pointers #tree
#Вперед #указатели #дерево
Вопрос:
У меня есть древовидная структура, где у любого узла может быть несколько дочерних элементов, но только один родительский. Узлы соединены указателями, и я хотел бы сохранить эту иерархию на карте, где я могу быстро получить доступ к дочерним и корневым узлам.
В настоящее время у меня есть версия, которая может выполнять желаемое поведение, но она сохраняет адреса входных данных на карте. Поэтому, если какой-либо из элементов на карте обновляется, он также обновляет исходную иерархию, чего я хотел бы избежать. Итак, я хотел бы сохранить точную копию моей иерархии на карте, которая имеет ту же структуру, но никак не связана с исходной. Что я делаю не так? Спасибо!
type node struct {
value string
children []*node
parent *node
}
// isRoot returns true if node is a root
func (node *node) isRoot() bool {
return node.parent == nil
}
var rootMap = make(map[string]*node)
var childrenMap = make(map[string]*node)
func main() {
/*
A
|
B
/
C D
*/
a := node{value: "a"}
b := node{value: "b", parent: amp;a}
c := node{value: "c", parent: amp;b}
d := node{value: "d", parent: amp;b}
a.children = []*node{amp;b}
b.children = []*node{amp;c, amp;d}
storeHierarchy(amp;a)
mappedA, _ := rootMap[a.value]
mappedB, _ := childrenMap[b.value]
fmt.Println(fmt.Sprintf("mappedA: %p, a: %p - not equal, which is perfect", mappedA, amp;a))
fmt.Println(fmt.Sprintf("mappedB: %p, a: %p - not equal, which is perfect", mappedB, amp;b))
fmt.Println(fmt.Sprintf("mappedA.child[0]: %p, a.child[0]: %p - these are equal, but should not be", mappedA.children[0], a.children[0]))
fmt.Println(fmt.Sprintf("mappedA.child[0]: %p, first child b: %p - these are not equal, but should be", mappedA.children[0], mappedB))
}
func storeHierarchy(order *node) {
orderCopy := *order
order = amp;orderCopy
for i := range order.children {
child := order.children[i]
storeHierarchy(child)
}
if order.isRoot() {
rootMap[order.value] = order
} else {
childrenMap[order.value] = order
}
}
Комментарии:
1. Ваш код создает копию узлов, которая включает в себя копирование
children
поля, которое является заголовком среза, дочерним элементам. Но вы никогда не меняете элементыchildren
, поэтому они будут одинаковыми. Также обратите внимание, что для глубокой копии также потребуется клонировать фрагмент, поскольку назначение заголовка фрагмента будет указывать на тот же резервный массив. Кроме того, вы не изменяетеparent
поля скопированных узлов, поэтому они будут указывать на исходные узлы.2. Спасибо за быстрый ответ. Позвольте мне попытаться исправить проблемы, о которых вы упомянули.