123 lines
2.8 KiB
Go
123 lines
2.8 KiB
Go
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) WeightingTreeWithRecursion() map[string]uint16 {
|
||
weight := root.getNodeWeight()
|
||
var res = make(map[string]uint16)
|
||
for _, v := range root.Children {
|
||
maps.Copy(res, v.WeightingTreeWithRecursion()) // Т.е. в go нет оптимизации хвостовой рекурсии, это породит неимоверное кол-во аллокаций.
|
||
weight = weight + res[v.ID]
|
||
}
|
||
res[root.ID] = weight
|
||
return res
|
||
}
|
||
|
||
func (root Node) WeightingTreeWithStack() map[string]uint16 {
|
||
weight := root.getNodeWeight()
|
||
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 := current.getNodeWeight()
|
||
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 := root.getNodeWeight()
|
||
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 := current.Value.(Node).getNodeWeight()
|
||
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 (n Node) getNodeWeight() uint16 {
|
||
nodeBytes, _ := json.Marshal(Node{
|
||
ID: n.ID,
|
||
Name: n.Name,
|
||
})
|
||
return uint16(len(nodeBytes))
|
||
}
|