该代码为数据结构实验任务四:哈夫曼树及哈夫曼编码实现。
输出第一行,为字符串中各个字符出现的次数
接下来为用表表示哈夫曼树
下一行为对字符串中各字符的编码
String Encode:字符串编码
String Decode:译码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define maxS 100 //字符串最大长度
#define maxE 10 //最大样本组数
#define maxC 6 //最大编码位数
//树结点结构
typedef struct{
int weight;
char ch;
int parent,lchild,rchild;
}HF;
//函数声明
void Encode(HF* hf,int n); //字符编码
char* SEncode(char *a,int n); //字符串编码
char* SDecode(char *a); //字符串译码
void PCodes(); //显示字符编码
void DFS(HF* hf,int n); //DFS遍历哈夫曼树
void Show(HF* hf,int n); //显示哈夫曼树
int count(char *a); //统计字符串中字符的出现频率
void Itr(HF* hf,int n); //哈夫曼遍历迭代
HF* Halfman(char *a,HF* hf); //构建哈夫曼编码树
int Read(char a[][maxS]); // 读取字符串
//全局变量
int fre[26]; //字母出现频率
char Codes[26][maxC]; //每个字母的编码
//输出编码
void PCodes(){
for(int i=0;i<26;i++){
if(Codes[i][0]!='\0'){
printf("%c:%s ",'a'+i,Codes[i]);
}
}
printf("\n");
}
//DFS遍历哈夫曼树并编码
void DFS(HF* hf,int n){
static char code[maxC]="";
static int cunt=0;
int flag = 0;
if(hf[n].lchild!=-1){
code[cunt++] = '0';
DFS(hf,hf[n].lchild);
cunt--;
flag = 1;
}
if(hf[n].rchild!=-1){
code[cunt++] = '1';
DFS(hf,hf[n].rchild);
cunt--;
flag = 1;
}
if(flag==0){
code[cunt] = '\0';
strcpy(Codes[hf[n].ch-'a'],code);
}
}
//查看哈夫曼树
void Show(HF* hf,int n){
int i=0;
printf("Halfman tree:\nAi C W L C P");
while(i<n){
printf("\n%d : %c %3d %3d %3d %3d",i,hf[i].ch,hf[i].weight,hf[i].lchild,hf[i].rchild,hf[i].parent);
i++;
}
printf("\n");
}
//统计频率,并返回总类别数
int count(char *a){
int rs=0;
for(int i=0;i<26;i++){
fre[i] = 0;
}
for(int i=0;i<maxS;i++){
if(a[i]>='a'&&a[i]<='z'){
fre[a[i]-'a']+=1;
}else{
a[i] = '\0';
break;
}
}
for(int i=0;i<26;i++){
if(fre[i]!=0)rs++;
}
return rs;
}
//哈夫曼树迭代并输出
void Itr(HF* hf,int n){
int min1,min2,turn,pos1,pos2;
printf("The frequence of letter:\n");
for(int i=0;i<n;i++){
printf("%c:%d ",hf[i].ch,hf[i].weight);
}
printf("\n");
for(int i=n;i<2*n-1;i++){
min1 = -1;
min2 = -1;
for(int j=i-1;j>=0;j--){
if(hf[j].parent==0){
if(min2==-1){
min2 = hf[j].weight;
pos2 = j;
continue;
}else if(min1==-1){
min1 = hf[j].weight;
pos1 = j;
continue;
}
}
if(min1>min2){
turn = min1;
min1 = min2;
min2 = turn;
turn = pos1;
pos1 = pos2;
pos2 = turn;
}
if(hf[j].weight<min2&&hf[j].parent==0){
min2 = hf[j].weight;
pos2 = j;
}
}
if(min1>min2){
turn = min1;
min1 = min2;
min2 = turn;
turn = pos1;
pos1 = pos2;
pos2 = turn;
}
hf[i].lchild = pos1;
hf[i].rchild = pos2;
hf[i].weight = min1+min2;
hf[i].parent= 0;
hf[i].ch='#';
hf[pos1].parent = i;
hf[pos2].parent = i;
}
Show(hf,2*n-1);
}
//哈夫曼树
HF* Halfman(char *a,HF* hf){
int num,n=0;
num = count(a); //统计频率,加载fre数组
hf = (HF*)malloc(sizeof(HF)*(2*num-1));
char *Sencode,*Sdecode;
//动态设计,加载HF数组初始化
for(int i=0;i<26;i++){
if(fre[i]!=0){
hf[n].lchild=-1;
hf[n].rchild=-1;
hf[n].ch = 'a'+i;
hf[n].weight=fre[i];
hf[n].parent = 0;
n++;
}
}
//HF数组迭代
printf("\n =================FZC=============== \n\n");
printf("[EXP]:\n");
Itr(hf,n);
printf("\n");
//对每个字符进行编码
Encode(hf,n);
PCodes();
//对字符串进行编码
Sencode = SEncode(a,strlen(a));
printf("\nString Encode:%s\n",Sencode);
//对字符串进行解码
Sdecode = SDecode(Sencode);
printf("\nString Decode:%s\n\n",Sdecode);
return hf;
}
//字母编码
void Encode(HF* hf,int n){
//清空原始数据
for(int i=0;i<26;i++){
strcpy(Codes[i],"");
}
DFS(hf,2*n-2);
}
//字符串编码
char* SEncode(char *a,int n){
char *rs = (char*)malloc(sizeof(char)*n*maxC);
int cunt=0;
for(int i=0;i<n;i++){
strcpy(rs+cunt,Codes[a[i]-'a']);
cunt+=strlen(Codes[a[i]-'a']);
}
return rs;
}
//字符串解码
char* SDecode(char *a){
char tmp[maxC]="";
char *rs = (char*)malloc(sizeof(char)*maxS);
int cunt = 0;
int tcunt=0;
for(int i=0;i<strlen(a);i++){
tmp[tcunt++] = a[i];
tmp[tcunt] = '\0';
for(int j=0;j<26;j++){
if(strcmp(tmp,Codes[j])==0){
rs[cunt++] = 'a'+j;
tcunt = 0;
}
}
}
rs[cunt]='\0';
return rs;
}
//读取字符串
int Read(char a[][maxS]){
int i,j;
printf("Please input the Strings and end with 0\n");
for(i=0;i<maxE;i++){
for(int j=0;j<maxS;j++)a[i][j]='#';
}
for(i=0;i<maxE;i++){
scanf("%s",a[i]);
if(a[i][0]=='0')break;
}
return i;
}
int main(){
char a[maxE][maxS];
HF *halfman[maxE];
int num=0;
num = Read(a); //读取字符串
printf("FOLLWING OUTPUT:\n\n");
for(int i=0;i<num;i++){
halfman[i] = Halfman(a[i],halfman[i]); //对每一组数据进行哈夫曼树构建
}
return 0;
}
该代码仅供参考,有任何问题欢迎交流。