代码拉取完成,页面将自动刷新
// ++++++++++++++++++++++++++++++++++++++++
// 《零基础Go语言算法实战》源码
// ++++++++++++++++++++++++++++++++++++++++
// Author:廖显东(ShirDon)
// Blog:https://www.shirdon.com/
// Gitee:https://gitee.com/shirdonl/goAlgorithms.git
// Buy link :https://item.jd.com/14101229.html
// ++++++++++++++++++++++++++++++++++++++++
package main
import (
"container/heap"
"fmt"
)
// 霍夫曼树接口
type HuffmanTree interface {
Freq() int
}
// 霍夫曼树子节点
type HuffmanLeaf struct {
freq int
value rune
}
func (huffman HuffmanLeaf) Freq() int {
return huffman.freq
}
// 霍夫曼节点
type HuffmanNode struct {
freq int
left, right HuffmanTree
}
func (huffman HuffmanNode) Freq() int {
return huffman.freq
}
// 最小堆
// 这是霍夫曼树最小堆的自定义实现。它是霍夫曼树切片的类型定义。
type minHeap []HuffmanTree
// 下面三个函数实现了Go中 heap 包所需要的接口
// 这使得minHeap类型可以与Go提供的内置堆函数一起使用。Len函数返回堆中元素的数量
func (th minHeap) Len() int { return len(th) }
// Less 函数用于比较堆中的两个元素并确定哪个更小。 在这里,它比较了两个 HuffmanTrees 的频率
// 如果第1棵树的频率小于第2棵树的频率,则返回真,表示第1棵树“小于”第2棵树
func (th minHeap) Less(i, j int) bool {
return th[i].Freq() < th[j].Freq()
}
// Push 函数用于向堆中添加新元素。它采用 interface{} 类型
// 然后将其类型断言为 HuffmanTree 类型并附加到切片
func (th *minHeap) Push(ele interface{}) {
*th = append(*th, ele.(HuffmanTree))
}
// Pop 函数用于从堆中移除最小的元素。它返回最小的元素(弹出)并将其从切片中移除
func (th *minHeap) Pop() (popped interface{}) {
popped = (*th)[len(*th)-1]
*th = (*th)[:len(*th)-1]
return
}
// Swap 函数用于交换两个元素在堆中的位置。它获取两个元素的索引并在切片中交换它们
func (th minHeap) Swap(i, j int) { th[i], th[j] = th[j], th[i] }
// 构建哈夫曼树并遍历打印代码的main()函数,构建的霍夫曼树
func buildTree(symFreqs map[rune]int) HuffmanTree {
var trees minHeap
for c, f := range symFreqs {
trees = append(trees, HuffmanLeaf{f, c})
}
heap.Init(&trees)
for trees.Len() > 1 {
// 频率最低的两棵树
a := heap.Pop(&trees).(HuffmanTree)
b := heap.Pop(&trees).(HuffmanTree)
// 放入新节点并重新插入队列
heap.Push(&trees, HuffmanNode{a.Freq() + b.Freq(), a, b})
}
return heap.Pop(&trees).(HuffmanTree)
}
// 从霍夫曼树的根部打印霍夫曼代码。 它使用 byte[] 来存储代码
func printCodes(tree HuffmanTree, prefix []byte) {
switch i := tree.(type) {
case HuffmanLeaf:
// 如果这是一个叶节点,那么它包含一个输入字符,从 byte[] 打印字符及其代码
fmt.Printf("%c\t%d\t%s\n", i.value, i.freq, string(prefix))
case HuffmanNode:
// 将 0 分配给左边缘并重复出现
prefix = append(prefix, '0')
printCodes(i.left, prefix)
prefix = prefix[:len(prefix)-1]
// 将 1 赋值给右边缘并重复出现
prefix = append(prefix, '1')
printCodes(i.right, prefix)
prefix = prefix[:len(prefix)-1]
}
}
func main() {
test := "abcdefghijklmnopqrstuvwxyz"
symFreqs := make(map[rune]int)
// 读取每个符号并记录频率
for _, c := range test {
symFreqs[c]++
}
// 示例树
exampleTree := buildTree(symFreqs)
// 打印结果
fmt.Println("符号霍夫曼码\t权重\t霍夫曼编码")
printCodes(exampleTree, []byte{})
}
//$ go run huffmanCode.go
//符号霍夫曼码 权重 霍夫曼编码
//d 1 0000
//v 1 0001
//w 1 0010
//s 1 0011
//p 1 0100
//x 1 0101
//n 1 01100
//y 1 01101
//u 1 01110
//f 1 01111
//b 1 10000
//q 1 10001
//z 1 10010
//l 1 10011
//a 1 10100
//r 1 10101
//k 1 10110
//i 1 10111
//j 1 11000
//t 1 11001
//m 1 11010
//c 1 11011
//g 1 11100
//h 1 11101
//e 1 11110
//o 1 11111
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。