#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MAXNUM 60
typedef struct
{
char ch;
int weight; //权值,这个字符出现的频率
int parent;
int left;
int right;
}HuffNode;
typedef struct
{
char code[MAXNUM];
int start;
}HuffCode;
HuffNode ht[MAXNUM*2]; //存放哈夫曼树
HuffCode hcd[MAXNUM]; //存放ht数组中对应的字符的编码
int n; //字符的个数
//初始化哈夫曼树ht
void initHt()
{
char ch;
int i;
printf("input the count of points:");
scanf("%d",&n);
int total=2*n-1;
for (i=0;i<total;i++)
{
ht[i].weight=0;
ht[i].parent=-1;
ht[i].left=-1;
ht[i].right=-1;
}
for (i=0;i<n;i++)
{
getchar();
printf ("Please input value of leaf node %d: \n", i);
scanf("%c",&ht[i].ch);
}
for (i=0;i<n;i++)
{
printf ("Please input weight of leaf node %d: \n", i);
scanf("%d",&ht[i].weight);
}
}
//构造哈夫曼树,看成有n棵树,选择权值最小的两棵树合并
void createHuffTree()
{
int i=0,k;
int minI,minJ;
int f=0;
minI=minJ=-1; //minI<minJ
for(k=n;k<2*n-1;k++){
//寻找ht中权值最小且无父结点的两个结点
i=0;
f=0;
while(ht[i].ch!='\0'){
if(ht[i].parent==-1){
if(f==0){
minI=i;
f++;
}else if(f==1){
if(ht[i].weight<ht[minI].weight){
minJ=minI;
minI=i;
}else
minJ=i;
f++;
}else{
if(ht[i].weight<ht[minI].weight){
minJ=minI;
minI=i;
}else if(ht[i].weight<ht[minJ].weight)
minJ=i;
}
}
i++;
}
//合并两个结点
ht[k].ch='#';
ht[k].left=minI;
ht[k].right=minJ;
ht[k].weight=ht[minI].weight+ht[minJ].weight;
ht[k].parent=-1;
ht[minI].parent=ht[minJ].parent=k;
}
}
//将一个字符串反转
void reverse(char *str)
{
int i,j;
char ch;
for(i=0,j=strlen(str)-1;i<j;i++,j--){
ch=str[i];
str[i]=str[j];
str[j]=ch;
}
}
//哈夫曼编码,通过父节点从下往上找
void createHuffCode()
{
int i,j,length;
for(i=0;i<n;i++){
length=0;
j=i;
//给每个字符进行编码
while(ht[j].parent!=-1){
if(ht[ht[j].parent].left==j){
hcd[i].code[length++]=0+'0';
}else
hcd[i].code[length++]=1+'0';
j=ht[j].parent;
}
hcd[i].start=hcd[i].code[length-1]-'0';
hcd[i].code[length]='\0';
reverse(hcd[i].code);
}
}
//哈夫曼解码,每次都从根节点开始搜索
int releaseHuffCode(char *str,char* code)
{
int root=2*n-2;
int length=0,i=0;
while(code[i]){
if(code[i]=='0'+0)
root=ht[root].left;
else if(code[i]=='0'+1)
root=ht[root].right;
else
return 0;
if(ht[root].left==-1 && ht[root].right==-1){
str[length++]=ht[root].ch;
root=2*n-2;
}
i++;
}
str[length]='\0';
if(root==2*n-2)
return 1;
return 0;
}
//用户输入编码字符
void encode()
{
int i=0,j,f=1;
char str[1000];
char code[1000]={'\0'};
printf("\n请输入要编码的字符串(length<1000)\n");
scanf("%s",str);
while(str[i]){
if(str[i]>='A'&&str[i]<='Z'){
for(j=0;j<n;j++)
if(str[i]==ht[j].ch){
strcat(code,hcd[j].code);
break;
}
i++;
}else{
f=0;
break;
}
}
if(f)
puts(code);
else
printf("你输入的字符串错误!\n");
printf("按任意键后重新选择!\n");
getchar();
}
//用户输入解码字串
void decode()
{
char str[1000];
char code[1000];
printf("\n请输入要解码的字串(用0和1表示)\n");
scanf("%s",code);
if(releaseHuffCode(str,code))
puts(str);
else
printf("你输入的字串错误!\n");
printf("按任意键后重新选择!\n");
getchar();
}
//主函数
int main()
{
int choice=1;
initHt();
createHuffTree();
createHuffCode();
while(choice){
printf("\n请输入你的选择:1 ---- 编码 2 ---- 解码 0 ---- 退出\n");
scanf("%d",&choice);
switch(choice){
case 1:
encode();
break;
case 2:
decode();
break;
case 0:
printf("退出!\n");
break;
default:
choice=1;
printf("你的输入错误!按任意键后重新输入!\n");
getchar();
break;
}
}
return 0;
}
测试数据:
/*
5
A
B
C
D
E
8
10
3
4
5
选择编码:ABBDE
结果为10111101100
*/