环境:突然间想要知道rpc为什么会受到欢迎,总结有以下几点
1.rpc是基于http2.0协议的
2.数据编码压缩减少了传输的数据量
http2.0 :基于https ,以及请求数据加密(更加安全),头部数据压缩(传输数据变少),引入流式传输以及请求方式
实现哈夫曼编码的流程:(这里只实现字符串编码和解码)
1.统计字符在字符串中出现的次数
2.按字符出现的次数从小到大排序
3.构建哈夫曼树
4.确定字典
5.把字符串替换成编号
哈夫曼解码就是按照字典去比对数据然后拼接
代码:
package Huffman
import "sort"
type NodeList []*Node
func (list NodeList) Len() int {
return len(list)
}
func (list NodeList) Swap(i, j int) {
list[i], list[j] = list[j], list[i]
}
func (list NodeList) Less(i, j int) bool {
return list[i].Weight < list[j].Weight
}
// Node 赫夫曼节点,用于构成赫夫曼树
type Node struct {
Weight uint //权重
Data string //数据
Parent *Node //父节点
Left *Node //左孩子
Right *Node //右孩子
}
// Tree 赫夫曼树结构
type Tree struct {
root *Node //根节点
leaf NodeList //所有叶子节点(即数据对应的节点)
src map[string]uint //源数据,key为数据,value为权重
codeSet map[string]string //编码集,key为数据,value为通过构造赫夫曼树得到的数据的编码
}
// NewHuffmanTree 给定一组字符及其权重的集合,初始化出一棵赫夫曼树
func NewHuffmanTree(src map[string]uint) *Tree {
var tree = &Tree{
src: src,
}
tree.init()
tree.build()
tree.parse()
return tree
}
// Coding 根据数据进行赫夫曼编码
func (h *Tree) Coding(target string) (result string) {
for _, t := range target {
v := string(t)
if c, ok := h.codeSet[v]; !ok {
panic("invalid code: " + v)
} else {
result += c
}
}
return result
}
// UnCoding 根据赫夫曼编码获取数据
func (h *Tree) UnCoding(target string) (result string) {
node := h.root
for i := 0; i < len(target); i++ {
switch target[i] {
case '0':
node = node.Left
case '1':
node = node.Right
}
if node.Left == nil && node.Right == nil {
result = result + node.Data
node = h.root
}
}
return
}
// 初始化所有叶子节点
func (h *Tree) init() {
if len(h.src) <= 1 {
panic("invalid src length.")
}
h.codeSet = make(map[string]string)
h.leaf = make(NodeList, len(h.src))
var i int
for data, weight := range h.src {
var node = &Node{
Weight: weight,
Data: data,
}
h.leaf[i] = node
i++
}
//对leaf根据权值排序
sort.Sort(h.leaf)
}
// 构造赫夫曼树
// src: key为data,value为权值
func (h *Tree) build() {
nodeList := h.leaf
//根据huffman树的规则构造赫夫曼树
for nodeList.Len() > 1 {
//1. 选取权值最小的两个node构造出第一个节点
var temp = &Node{
Weight: nodeList[0].Weight + nodeList[1].Weight,
Left: nodeList[0],
Right: nodeList[1],
}
nodeList[0].Parent = temp
nodeList[1].Parent = temp
//2.将生成的新节点插入节点序列中
nodeList = newList(nodeList[2:], temp)
}
h.root = nodeList[0]
}
/*
找出每一个字符对应的编码
*/
func (h *Tree) parse() {
if h.root == nil {
return
}
var temp *Node
var code string
for _, n := range h.leaf {
temp = n
for temp.Parent != nil {
if temp == temp.Parent.Left {
code = "0" + code
} else {
code = "1" + code
}
temp = temp.Parent
}
h.codeSet[n.Data] = code
code = ""
}
}
// 将生成的节点放入节点列表,列表始终按照从小到大排序
func newList(src NodeList, temp *Node) NodeList {
length := len(src)
result := make(NodeList, len(src)+1)
if length == 0 {
result[0] = temp
return result
}
if src[length-1].Weight <= temp.Weight {
copy(result, src)
result[length] = temp
return result
}
for i := range src {
if src[i].Weight <= temp.Weight {
result[i] = src[i]
} else {
result[i] = temp
copy(result[i+1:], src[i:])
break
}
}
return result
}
测试代码:
package main
import (
"fmt"
"strings"
"webIm/Huffman"
)
func main() {
str := "霍夫曼编码(Huffman Coding)是一种编码方法,霍夫曼编码是可变字长编码(VLC)的一种。\n\n霍夫曼编码使用变长编"
fmt.Println(str)
/**
1.计算每个字符的出现次数
2.按照出现次数从小到大排序
3.构建哈夫曼树
4.确定字符的路径(编号)
5.用编号替换字符
**/
mapStr := make(map[string]uint)
strSpli := strings.Split(str, "")
for _, v := range strSpli {
if _, ok := mapStr[v]; ok {
mapStr[v]++
} else {
mapStr[v] = 1
}
}
treeHaf := Huffman.NewHuffmanTree(mapStr)
HuffmanCode := treeHaf.Coding(str)
println(HuffmanCode)
println(treeHaf.UnCoding(HuffmanCode))
}
思考:在实际运用当中哈夫曼编码用byte去存而不是用字符串