什么是霍夫曼编码:
哈夫曼编码(Huffman Coding),又称霍夫曼编码,是一种编码方式,哈夫曼编码是可变字长编码(VLC)的一种。Huffman于1952年提出一种编码方法,该方法完全依据字符出现概率来构造异字头的平均长度最短的码字,有时称之为最佳编码,一般就叫做Huffman编码(有时也称为霍夫曼编码)。
用处:
压缩文本
构造思路:
根据给定的 n 个权值
Wi ,构成 n 颗二叉树的集合F ,其中每颗二叉树只对应一个节点,其左右子树问空在 F 中选取两颗根权值最小的二叉树作为左右子树构造一颗新的二叉树,新的二叉树根节点的权值为其左右子树根节点的权值之和。
- 在
F 中删除这两颗子树,同时将新的二叉树加入集合 F .- 重复2,3,知道集合
F 中只有一颗二叉树为止,这棵树便是霍夫曼树。
实现代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <stdlib.h>
#include <limits.h>
#include <time.h>
using namespace std;
const int MAX = INT_MAX;
const int MAX_LEN = 100;
typedef struct node
{
int val;
int lchild,rchild,parent;
node() {
val = 0;
lchild = rchild = parent = -1;
}
node(int _v,int _l,int _r,int _p) {
val = _v,lchild = _l,rchild = _r,parent = _p;
}
}Hnode;
typedef struct Hcode
{
int bit[MAX_LEN];
int start;
}Hcode;
void HuffmanCoding(int w[],int n)
{
if(n <= 1) return ;
int i,j,m = 2*n -1;
Hnode *H;
H = (Hnode *)malloc(m*sizeof(Hnode));
for(i = 0;i < m;i ++) {
H[i] = node((i<n?w[i]:0),-1,-1,-1);
}
/*构造霍夫曼树*/
for(i = n;i < m; i++) {
int m1 = MAX, m2 = MAX;
int x1 = -1,x2 = -1;
for(j = 0;j < i;j ++) {
if(H[j].parent != -1) continue;
if(H[j].val < m1) {
m2 = m1, m1 = H[j].val;
x2 = x1, x1 = j;
}
else if(H[j].val < m2) {
m2 = H[j].val, x2 = j;
}
}
H[i] = node(m1+m2,x1,x2,-1);
H[x1].parent = H[x2].parent = i;
}
/*霍夫曼编码*/
Hcode *HC;
HC = (Hcode *)malloc(n*sizeof(Hcode));
for(i = 0;i < n;i ++) {
int cnt = n-1;
for(int s = i;s != -1;s = H[s].parent) {
int p = H[s].parent;
if(p == -1) break;
if(H[p].lchild == s) HC[i].bit[cnt--] = 0;
else {
HC[i].bit[cnt--] = 1;
}
}
HC[i].start = cnt + 1;//记录编码的起始位置
}
/*测试*/
/*
for(int i = 0;i < n;i ++) {
cout<<"第"<<i<<"个字符编码为:\n";
for(int j = HC[i].start;j < n;j ++) {
cout<<HC[i].bit[j]<<" ";
}
cout<<"\n";
}
*/
}
int main()
{
/*测试*/
srand((unsigned int)time(NULL));
int *w,n = 1 + rand()%20;
w = (int *)malloc(n*sizeof(int));
for(int i = 0;i < n;i ++) {
w[i] = 1 + rand()%100;
cout<<w[i]<<endl;
}
HuffmanCoding(w,n);
return 0;
}