# 霍夫曼编码及实现

### 构造思路:

• 根据给定的n$n$个权值Wi$W_i$，构成n$n$ 颗二叉树的集合F$F$，其中每颗二叉树只对应一个节点，其左右子树问空

• F$F$中选取两颗根权值最小的二叉树作为左右子树构造一颗新的二叉树，新的二叉树根节点的权值为其左右子树根节点的权值之和。

• F$F$中删除这两颗子树，同时将新的二叉树加入集合F$F$.
• 重复2,3，知道集合F$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;
}

forever_24

• 擅长领域：
• 机器学习
• 统计分析