霍夫曼编码约定
Convention for Huffman Coding
是否有为特定字母表生成霍夫曼编码的约定?看起来生成的编码取决于您是将“0”分配给左侧 child 还是右侧 child 以及您如何确定哪个符号将进入左侧树。
Wikipedia 表示:
As a common convention, bit '0' represents following the left child
and bit '1' represents following the right child.
所以这是前半部分方差的答案。但是,我找不到下半场的任何惯例。我会假设一些事情,比如让概率较低的节点在左边,但几个在线霍夫曼树示例不会这样做。
例如:
那么左右节点的分配有没有约定俗成的,还是要看实现?
如果这是重复的,我深表歉意,但我找不到答案。
是的,事实上是有的。与其说是互操作性约定,不如说是编码效率约定。称为Canonical Huffman,其中代码按从最短代码到最长代码的数字顺序分配,并且在单个代码长度内,它们在符号上按字典顺序分配。这允许只传输每个符号的代码长度,而不是整个树结构。
一般做的只是用哈夫曼算法树来确定每个符号的比特数。然后树被丢弃。位值永远不会分配给分支。然后使用上面的顺序直接根据长度构建代码。
看看
class Nodo{
constructor(v=null,f=null,l=null,r=null){
this.f=f
this.v=v
this.l=l
this.r=r
}
}
function EnCrypt(text){
let lista=[]
for(let i=0;i<text.length;i++){//Create the list with the appearances
!lista.find(e => e.v===text[i]) && lista.push(new Nodo(text[i],(text.match(new RegExp(text[i],"g")) || []).length))
}
lista=lista.sort((a,b)=>a.f-b.f)//Order from smallest to largest
//----------------------------------------------------
function createNew(){//Create the tree
let nodos=lista.splice(0,2)
lista.push(new Nodo(null,nodos[0].f+nodos[1].f,nodos[0],nodos[1]))
if(lista.length==1)return lista
createNew()
}createNew()
///-----------------------------------------------
let Arbol=lista[0]
function Codigo(nodo,c=""){//recursively traverse the tree
if(!nodo.l && !nodo.r)return [nodo.v,c]
return Codigo(nodo.l,c+"0")+";"+Codigo(nodo.r,c+"1")
}
//-----------------------------------------------
const codigo=(Codigo(Arbol)).split(";")
let finish=""
text.split("").map(t=>{
codigo.map(e => {
if(e.split(",")[0]==t)finish+=e.split(",")[1]
})
})
return {
cod:finish,
dicc:codigo
}
}
function DeCrypt(key,res=""){
let {cod,dicc}=key
let temp=""
for(let i=0;i<=cod.length;i++){
temp+=cod.substr(i,1)
dicc.map((d)=>{
d=d.split(",")
if(temp==d[1]){
res+=d[0]
temp=""
cod=cod.substr(i)
i=0
}
})
}
return res
}
function Huffman(){
const text=document.querySelector("#newValue").value
const comp= EnCrypt(text)
document.querySelector(".res").innerHTML=JSON.stringify(comp,null, 4)
}
function HuffmanDecode(){
const text=JSON.parse(document.querySelector("#huffman").value)
const comp= DeCrypt(text)
document.querySelector(".res2").innerHTML=comp
}
<h1></h1>
<input type="text"
placeholder="set value (min 2 chars)" id="newValue">
<button onclick="Huffman()">Go</button>
<div class="res" style="white-space: pre-wrap;"></div>
<input type="text" placeholder="paste the result from above" id="huffman"><button onclick="HuffmanDecode()">decode</button>
<div class="res2" style="white-space: pre-wrap;"></div>
是否有为特定字母表生成霍夫曼编码的约定?看起来生成的编码取决于您是将“0”分配给左侧 child 还是右侧 child 以及您如何确定哪个符号将进入左侧树。
Wikipedia 表示:
As a common convention, bit '0' represents following the left child and bit '1' represents following the right child.
所以这是前半部分方差的答案。但是,我找不到下半场的任何惯例。我会假设一些事情,比如让概率较低的节点在左边,但几个在线霍夫曼树示例不会这样做。
例如:
那么左右节点的分配有没有约定俗成的,还是要看实现?
如果这是重复的,我深表歉意,但我找不到答案。
是的,事实上是有的。与其说是互操作性约定,不如说是编码效率约定。称为Canonical Huffman,其中代码按从最短代码到最长代码的数字顺序分配,并且在单个代码长度内,它们在符号上按字典顺序分配。这允许只传输每个符号的代码长度,而不是整个树结构。
一般做的只是用哈夫曼算法树来确定每个符号的比特数。然后树被丢弃。位值永远不会分配给分支。然后使用上面的顺序直接根据长度构建代码。
看看
class Nodo{
constructor(v=null,f=null,l=null,r=null){
this.f=f
this.v=v
this.l=l
this.r=r
}
}
function EnCrypt(text){
let lista=[]
for(let i=0;i<text.length;i++){//Create the list with the appearances
!lista.find(e => e.v===text[i]) && lista.push(new Nodo(text[i],(text.match(new RegExp(text[i],"g")) || []).length))
}
lista=lista.sort((a,b)=>a.f-b.f)//Order from smallest to largest
//----------------------------------------------------
function createNew(){//Create the tree
let nodos=lista.splice(0,2)
lista.push(new Nodo(null,nodos[0].f+nodos[1].f,nodos[0],nodos[1]))
if(lista.length==1)return lista
createNew()
}createNew()
///-----------------------------------------------
let Arbol=lista[0]
function Codigo(nodo,c=""){//recursively traverse the tree
if(!nodo.l && !nodo.r)return [nodo.v,c]
return Codigo(nodo.l,c+"0")+";"+Codigo(nodo.r,c+"1")
}
//-----------------------------------------------
const codigo=(Codigo(Arbol)).split(";")
let finish=""
text.split("").map(t=>{
codigo.map(e => {
if(e.split(",")[0]==t)finish+=e.split(",")[1]
})
})
return {
cod:finish,
dicc:codigo
}
}
function DeCrypt(key,res=""){
let {cod,dicc}=key
let temp=""
for(let i=0;i<=cod.length;i++){
temp+=cod.substr(i,1)
dicc.map((d)=>{
d=d.split(",")
if(temp==d[1]){
res+=d[0]
temp=""
cod=cod.substr(i)
i=0
}
})
}
return res
}
function Huffman(){
const text=document.querySelector("#newValue").value
const comp= EnCrypt(text)
document.querySelector(".res").innerHTML=JSON.stringify(comp,null, 4)
}
function HuffmanDecode(){
const text=JSON.parse(document.querySelector("#huffman").value)
const comp= DeCrypt(text)
document.querySelector(".res2").innerHTML=comp
}
<h1></h1>
<input type="text"
placeholder="set value (min 2 chars)" id="newValue">
<button onclick="Huffman()">Go</button>
<div class="res" style="white-space: pre-wrap;"></div>
<input type="text" placeholder="paste the result from above" id="huffman"><button onclick="HuffmanDecode()">decode</button>
<div class="res2" style="white-space: pre-wrap;"></div>