霍夫曼编码导致输出错误但长度正确

时间:2019-03-29 11:47:52

标签: go priority-queue huffman-code

我正在尝试实现霍夫曼树,以对消息进行解码/编码,这是分配的一部分。当我得到正确的长度时,我似乎在代码中的某个地方出错了,我可以通过执行等级顺序来确认。

我在哪里做错了?会喜欢一些提示或指导

我一直在尝试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。”

0 个答案:

没有答案