我正在尝试实现霍夫曼树,以对消息进行解码/编码,这是分配的一部分。当我得到正确的长度时,我似乎在代码中的某个地方出错了,我可以通过执行等级顺序来确认。
我在哪里做错了?会喜欢一些提示或指导
我一直在尝试minHeap / priority队列的许多不同实现,但是代码的当前状态是最接近结果的状态。
package main
import (
"fmt"
"sort"
)
const nullchar = '\x00'
type treeNode struct {
left, right *treeNode
letter rune
frequency int
}
type tree struct {
root *treeNode
}
func makeNode(letter rune) *treeNode {
return &treeNode{
letter: letter,
frequency: 1,
}
}
func makePriorityQueue(letters []*treeNode, byAlpha bool) {
// sort queue into priotiry queue after frequency
sort.Slice(letters, func(i, j int) bool {
if byAlpha {
return letters[i].letter < letters[j].letter
}
return letters[i].frequency < letters[j].frequency
})
}
func mapRunesToNodes(message string) []*treeNode {
letters := make([]*treeNode, 0)
for _, letter := range message {
containsLetter := false
for _, node := range letters {
if node != nil && node.letter == letter {
node.frequency++
containsLetter = true
break
}
}
if !containsLetter {
letters = append(letters, makeNode(letter))
}
}
return letters
}
func printPriorityQueue(letters []*treeNode) {
for _, node := range letters {
if node != nil {
fmt.Println(node)
}
}
}
func makeHuffmanTree(letters []*treeNode) *tree {
tree := new(tree)
if len(letters) == 1 {
tree.root = letters[0]
return tree
}
for len(letters) > 1 {
root := &treeNode{
letter: nullchar,
left: letters[0],
right: letters[1],
frequency: letters[0].frequency + letters[1].frequency,
}
letters = append(letters, root)
letters = append(letters[:0], letters[2:]...)
makePriorityQueue(letters, false)
}
tree.root = letters[0]
return tree
}
func levelOrder(root *treeNode) [][]int {
res := [][]int{}
var dfs func(*treeNode, int)
dfs = func(root *treeNode, level int) {
if root == nil {
return
}
if level >= len(res) {
res = append(res, []int{})
}
res[level] = append(res[level], root.frequency)
dfs(root.left, level+1)
dfs(root.right, level+1)
}
dfs(root, 0)
return res
}
func (root *treeNode) isLeaf() bool {
return root.left == nil && root.right == nil
}
// visit current subtree
func (root *treeNode) traverse(encodeMap *map[rune]string, code string) *map[rune]string {
if root == nil {
return encodeMap
}
if root.isLeaf() {
(*encodeMap)[root.letter] = code
}
root.left.traverse(encodeMap, code+"0")
root.right.traverse(encodeMap, code+"1")
return encodeMap
}
func encode(root *treeNode) map[rune]string {
encodedMap := make(map[rune]string)
root.traverse(&encodedMap, "")
fmt.Println(encodedMap)
return encodedMap
}
func main() {
toEncode := "i love computer science"
toDecode := "110010111010000110111111011000000111000110010011111110100101010110011001110110100111"
queue := mapRunesToNodes(toEncode)
makePriorityQueue(queue, true)
//printPriorityQueue(queue)
huffmanTree := makeHuffmanTree(queue)
/*level := levelOrder(huffmanTree.root)
num := 0
for i, l := range level {
fmt.Printf("LEVEL %d: %v\n", i+1, l)
num += len(l)
}
fmt.Printf("NUM NODES: %d\n", num)*/
encodedMap := encode(huffmanTree.root)
output := ""
for _, v := range toEncode {
output += encodedMap[v]
}
fmt.Printf("\n\nMATCHING: %v\nENCODED: %s\nTARGET: %s\n", output == toDecode, output, toDecode)
/*for k, v := range encodedMap {
fmt.Printf("%s %s\n", string(k), v)
}*/
}
在对字符串运行编码后,我希望变量“ toEncode”的结果等于变量“ toDecode”。
老师的注释可能有助于调试:“最初将字符添加到优先级队列时,请在 按字母顺序。例如,如果您的频率图是:b:2,c:1,x:1,a:4, [space]:3,那么您可以按以下顺序将它们添加到优先级队列中:[space],a,b,c,x。”