You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

132 lines
2.3 KiB

  1. package huffman
  2. import (
  3. "fmt"
  4. "sort"
  5. )
  6. const (
  7. LEAF = 0
  8. MID = 1
  9. )
  10. type Node struct {
  11. typ int64
  12. key int64
  13. leaf byte
  14. l *Node
  15. r *Node
  16. }
  17. func (n *Node) String() string {
  18. if n.typ == LEAF {
  19. return fmt.Sprintf("%s (%v)", string(n.leaf), n.key)
  20. }
  21. return fmt.Sprintf("%v", n.key)
  22. }
  23. func newLeaf(b byte, k int64) *Node {
  24. return &Node{
  25. typ: LEAF,
  26. key: k,
  27. leaf: b,
  28. }
  29. }
  30. func newNode(a, b *Node) *Node {
  31. var l, r *Node
  32. if a.key < b.key {
  33. l = a
  34. r = b
  35. } else {
  36. l = b
  37. r = a
  38. }
  39. n := &Node{
  40. typ: MID,
  41. key: a.key + b.key,
  42. l: l,
  43. r: r,
  44. }
  45. return n
  46. }
  47. func leafsFromValues(values map[byte]int64) []*Node {
  48. var nodes []*Node
  49. for k, v := range values {
  50. n := newLeaf(k, v)
  51. nodes = append(nodes, n)
  52. }
  53. return nodes
  54. }
  55. func rmFromNodes(i int, nodes []*Node) []*Node {
  56. if i == len(nodes) {
  57. return nodes[:i]
  58. }
  59. return append(nodes[:i], nodes[i+1:]...)
  60. }
  61. // sortNodes returns a []*Node sorted
  62. func sortNodes(nodes []*Node) []*Node {
  63. sort.Slice(nodes, func(i, j int) bool {
  64. return nodes[i].key < nodes[j].key
  65. })
  66. return nodes
  67. }
  68. func buildTree(nodes []*Node) *Node {
  69. // build binary tree
  70. for len(nodes) > 1 {
  71. // pair two smallest nodes
  72. nodes = sortNodes(nodes)
  73. // create a new node with them
  74. n := newNode(nodes[0], nodes[1])
  75. // remove the picked nodes from the array of nodes
  76. nodes = rmFromNodes(0, nodes)
  77. nodes = rmFromNodes(0, nodes)
  78. // add the new node (the two old paired) to the node array
  79. nodes = append(nodes, n)
  80. }
  81. return nodes[0]
  82. }
  83. func descendTable(n *Node, path string, table map[byte]string) map[byte]string {
  84. if n.typ == MID {
  85. table = descendTable(n.l, path+"0", table)
  86. table = descendTable(n.r, path+"1", table)
  87. } else if n.typ == LEAF {
  88. table[n.leaf] = path
  89. }
  90. return table
  91. }
  92. func generateTable(n *Node) map[byte]string {
  93. table := make(map[byte]string)
  94. table = descendTable(n, "", table)
  95. return table
  96. }
  97. func Huffman(b []byte) error {
  98. // compute frequencies
  99. values := make(map[byte]int64)
  100. for _, v := range b {
  101. values[v]++
  102. }
  103. leafs := leafsFromValues(values)
  104. // sort frequencies
  105. sortedLeafs := sortNodes(leafs)
  106. // build binary tree
  107. n := buildTree(sortedLeafs)
  108. fmt.Println(n)
  109. // get the table (binary code for each value)
  110. table := generateTable(n)
  111. fmt.Println(table)
  112. // WIP
  113. return nil
  114. }