之前在写实验的时候在b站发了一个讲解视频:哈夫曼编码代码讲解
有不少人来问我要代码,决定还是发一个吧。
运行结果如下:
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<string>
#define maxn 100
using namespace std;
typedef char **HuffmanCode;//二级指针
int start; //cd数组的下标指针
char *cd; //用来临时存放当前正在求解的第i个字符的编码
typedef struct
{
int weight;//权重
int parent,lchild,rchild;//双亲,左孩子,右孩子
}HTNode,*HuffmanTree;
void init_HuffmanTree(HuffmanTree &HT,int n)
{
int m;
m=2*n-1;
HT=new HTNode[m+1];//分配m+1个单元,从1-m存数据
for(int i=0;i<=m;i++)//初始化,注意是m,不是n
{
HT[i].parent=0;
HT[i].lchild=0;
HT[i].rchild=0;
}
}
void Select(HTNode HT[],int &S1,int &S2,int m)
{
int i;
int minweight=10000;//设置一个最小权重
for(i=1;i<m;i++)//遍历找到最小
{
if(HT[i].weight<minweight&&HT[i].parent==0)
{
minweight=HT[i].weight;
S1=i;
}
}
minweight=10000;
for(i=1;i<m;i++)//遍历找到次小
{
if(HT[i].weight<minweight&&HT[i].parent==0& i!=S1)
{
minweight=HT[i].weight;
S2=i;
}
}
}
void CreateHuffmanTree(HuffmanTree &HT, int n)
{
int m,s1,s2,i;
int &S1=s1,&S2=s2;
if(n<=1) return;
m=2*n-1;
for(i=n+1;i<=m;i++)//n-1选择,删除合并来创建
{
Select(HT,S1,S2,i);// 在双亲是0的结点中选择较小两个
//cout<<s1<<" "<<s2<<endl;
HT[s1].parent=i;
HT[s2].parent=i;//更新双亲域
HT[i].rchild=s1;//更新孩子域
HT[i].lchild=s2;
HT[i].weight=HT[s1].weight+HT[s2].weight;//更新权重
}
}
void CreateHuffmanCode(HuffmanTree HT,HuffmanCode &HC,int n)
{
int c,f,start;
HC=new char*[n+1];
cd= new char[n];
cd[n-1]='\0';//存放每个字符编码的临时数组
for(int i=1;i<=n;i++)
{
start=n-1;
c=i;
f=HT[i].parent;//f指向c的双亲
while (f!=0)
{
--start;
if(HT[f].lchild==c) //左0右1
cd[start]='0';
else
cd[start]='1';
c=f;
f=HT[f].parent;
}
//[] HC[i]=a;a,是一维数组的首地址。
HC[i]=new char[n-start];
strcpy(HC[i],&cd[start]);//复制
}
delete cd;
}
int main()
{
//char ch[maxn],*p;
char *p;
string ch[maxn];
int n,i;
HuffmanTree HT;
HuffmanTree &H=HT;//引用型变量
HuffmanCode code;
HuffmanCode &HC=code;//引用型变量
cout<<"请输入要编码的字符个数,并输入字符和其对应的频数"<<endl;
cin>>n;
init_HuffmanTree(H,n);
for(i=1;i<=n;i++)//输入字符和权重
cin>>ch[i]>>HT[i].weight;
CreateHuffmanTree(H,n);
cout<<endl;//输出哈夫曼树
for(i=1;i<=2*n-1;i++)
cout<<HT[i].weight<<" "<<HT[i].parent<<" "<<HT[i].rchild<<" "<<HT[i].lchild<<endl;
//cout<<ch[i]<<" "<<H[i].weight<<endl;
CreateHuffmanCode(HT,HC,n);
for(i=1;i<=n;i++)//输出编码
{
cout<<ch[i]<<" ";//先输出字符
p=code[i];//数组首地址
while (*p!='\0')//没到\0时一直输出
{
cout<<*p;
p++;
}
cout<<endl;
}
return 0;
}
// 8
// a 5
// b 29
// c 7
// d 8
// e 14
// f 23
// g 3
// h 11