-
哈夫曼编码
编辑
哈夫曼编码(Huffman Coding),又称霍夫曼编码,是一种编码方式,哈夫曼编码是可变
字长编码(VLC)的一种。Huffman于1952年提出一种编码方法,该方法完全依据
字符出现概率来构造异字头的平均长度最短的码字,有时称之为最佳编码,一般就叫做Huffman编码(有时也称为霍夫曼编码)。
/*************************************
摘自百科百度******************************************************/
代码实现:
#include <iostream>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <string.h>
#define INF 0x3f3f3f3f
using namespace std;
typedef struct{
char ch;
int data;//频率
int p,lc,rc;
}Htree,*Hufftree;
typedef char* Huffcode;
int min1_ad,min2_ad;//这两个全局变量,记录最小权值的位置
int m;//m=2*n-1
void select(Hufftree &Ht,int j){
min1_ad=0,min2_ad=0;//原来写的代码为:int min1_ad=0,min2_ad=0,多了一个int
int min1=INF,min2=INF;//min1第一小的数、min2第二小的数
for(int k=0;k<=j;k++){
if(!Ht[k].p){//如果有父节点,跳过。之前用的while,这会使下面的程序段一直执行,而不跳出
if(Ht[k].data<min1){
min2=min1;
min2_ad=min1_ad;
min1=Ht[k].data;
min1_ad=k;
}
else if(Ht[k].data<min2){
//比最小数min1大 ,但是比当前第二小的数大
min2_ad=k;
min2=Ht[k].data;
}
}
}
}
void Huffman(Hufftree &Ht,Huffcode Hc[],int frequency[],char str[],int n){
if (n<1)return ;
m=2*n-1;//链表总长度
Ht=(Htree*)malloc((m)*sizeof(Htree));
for(int i=0;i<n;i++){
Ht[i].data=frequency[i];
Ht[i].ch=str[i];
Ht[i].lc=-1; Ht[i].p=0; Ht[i].rc=-1;
}//录入数据
for(int i=n;i<m;i++){
Ht[i].data=0;
Ht[i].lc=-1; Ht[i].p=0; Ht[i].rc=-1;
}//初始化
for(int i=n;i<m;i++){
select(Ht,i-1);//找到最小的无父节点的两个数,位置储存在s1,s2
/*错误原码
Ht[i].lc=Ht[min1_ad].p;
Ht[i].rc=Ht[min2_ad].p;*/
Ht[i].lc=min1_ad;//建立父子关系
Ht[i].rc=min2_ad;
Ht[i].data=Ht[min1_ad].data+Ht[min2_ad].data;
Ht[min1_ad].p=i;
Ht[min2_ad].p=i;
}
int start=0;
char *cd ;
cd =(char*)malloc(n*sizeof(char));//储存每个变量的哈夫曼编码
cd[n-1]='\0';
for(int i=0;i<n;i++){
start=n-1;
for(int c=i,f=Ht[i].p;f!=0;c=f,f=Ht[f].p){//顺着父节点向上倒溯
if (Ht[f].lc==c)
cd[--start]='0';
else
cd[--start]='1';
/*if(Ht[f].lc==c){//左孩子为Ht[c]
cd[start]='0';
start--;
}
else {//右边孩子为Ht[c]
cd[start]='1';
start--;
}*/
}
Hc[i]=(char*)malloc((n-start)*sizeof(char));
//Hc[1]=一个对应的动态数组
strcpy(Hc[i],&cd[start]);
//从start开始,而不是cd[0]
}
free(cd);
}
int main (){
int n; cout<<"请输入字符个数:"<<endl; cin >>n;
char *str;
str =(char*)malloc((n)*sizeof(char));
cout<<"请依次输入字符:"<<endl;
for(int i=0;i<n;i++)cin>>str[i];
// for(int i=0;i<n;i++)cout<<str[i]<<" ";
// cout<<endl;
int *frequency;
frequency=(int*)malloc((n)*sizeof(int));
cout<<"请依次输入字符出现次数:"<<endl;
for(int i=0;i<n;i++)cin>>frequency[i];
// for(int i=0;i<n;i++)cout<<frequency[i]<<" ";
// cout<<endl;
Hufftree Ht; Huffcode *Hc;
Hc=(Huffcode*)malloc(n*sizeof(Huffcode));
Huffman(Ht,Hc,frequency,str,n);
// for (int i=0;i<(2*n-1);i++)cout<<Ht[i].data<<" ";
// cout<<endl;
cout<<"字符 哈夫曼编码"<<endl;
for(int i=0;i<n;i++)cout<<str[i]<<" "<<Hc[i]<<endl;
free(str);free(frequency);free(Ht);free(Hc);
//释放内存空间
}
运行结果:
(水平所限,如有不对,敬请斧正)