package huffman import ( "fmt" "sort" ) const ( LEAF = 0 MID = 1 ) type Node struct { typ int64 key int64 leaf byte l *Node r *Node } func (n *Node) String() string { if n.typ == LEAF { return fmt.Sprintf("%s (%v)", string(n.leaf), n.key) } return fmt.Sprintf("%v", n.key) } func newLeaf(b byte, k int64) *Node { return &Node{ typ: LEAF, key: k, leaf: b, } } func newNode(a, b *Node) *Node { var l, r *Node if a.key < b.key { l = a r = b } else { l = b r = a } n := &Node{ typ: MID, key: a.key + b.key, l: l, r: r, } return n } func leafsFromValues(values map[byte]int64) []*Node { var nodes []*Node for k, v := range values { n := newLeaf(k, v) nodes = append(nodes, n) } return nodes } func rmFromNodes(i int, nodes []*Node) []*Node { if i == len(nodes) { return nodes[:i] } return append(nodes[:i], nodes[i+1:]...) } // sortNodes returns a []*Node sorted func sortNodes(nodes []*Node) []*Node { sort.Slice(nodes, func(i, j int) bool { return nodes[i].key < nodes[j].key }) return nodes } func buildTree(nodes []*Node) *Node { // build binary tree for len(nodes) > 1 { // pair two smallest nodes nodes = sortNodes(nodes) // create a new node with them n := newNode(nodes[0], nodes[1]) // remove the picked nodes from the array of nodes nodes = rmFromNodes(0, nodes) nodes = rmFromNodes(0, nodes) // add the new node (the two old paired) to the node array nodes = append(nodes, n) } return nodes[0] }