package main import ( "encoding/json" "maps" "tests/cut_the_tree/dll" ) type Node struct { ID string `json:"id"` Name string `json:"name"` Children []*Node `json:"children"` } type WeightedNode struct { parent string weight uint16 } func (root Node) WeighingTreeWithRecursion() map[string]uint16 { weight := getNodeWeight(root.ID, root.Name) var res = make(map[string]uint16) for _, v := range root.Children { maps.Copy(res, v.WeighingTreeWithRecursion()) // Т.е. в go нет оптимизации хвостовой рекурсии, это породит неимоверное кол-во аллокаций. weight = weight + res[v.ID] } res[root.ID] = weight return res } func (root Node) WeighingTreeWithStack() map[string]uint16 { weight := getNodeWeight(root.ID, root.Name) counter := map[string]*WeightedNode{root.ID: { weight: weight, }} stack := []*Node{&root} for len(stack) > 0 { current := stack[len(stack)-1] stack = stack[:len(stack)-1] nodeWeight := getNodeWeight(current.ID, current.Name) counter[current.ID].weight = nodeWeight // Прибавляем вес всем родительским нодам до корня parentID := counter[current.ID].parent for { currentNode := counter[parentID] if parentID == "" { break } currentNode.weight = currentNode.weight + nodeWeight parentID = currentNode.parent } for _, child := range current.Children { counter[child.ID] = &WeightedNode{ parent: current.ID, } stack = append(stack, child) } } var res = make(map[string]uint16) for k, v := range counter { res[k] = v.weight } return res } func (root Node) WeightingTreeWithDLL() map[string]uint16 { weight := getNodeWeight(root.ID, root.Name) counter := map[string]*WeightedNode{root.ID: { weight: weight, }} dllist := dll.NewList() dllist.PushFront(root) for dllist.Len() > 0 { current := dllist.Front() dllist.Remove(current) nodeWeight := getNodeWeight(current.Value.(Node).ID, current.Value.(Node).Name) counter[current.Value.(Node).ID].weight = nodeWeight // Прибавляем вес всем родительским нодам до корня parentID := counter[current.Value.(Node).ID].parent for { currentNode := counter[parentID] if parentID == "" { break } currentNode.weight = currentNode.weight + nodeWeight parentID = currentNode.parent } for _, child := range current.Value.(Node).Children { counter[child.ID] = &WeightedNode{ parent: current.Value.(Node).ID, } dllist.PushFront(*child) } } var res = make(map[string]uint16) for k, v := range counter { res[k] = v.weight } return res } func (root Node) DecomposeTree(weights map[string]uint16, limit int) ([]*Node, error) { return nil, nil } func getNodeWeight(id string, name string) uint16 { nodeBytes, _ := json.Marshal(Node{ ID: id, Name: name, }) return uint16(len(nodeBytes)) }