1.头文件HuffmanTree.h
#include <malloc.h>
#include <stdio.h>
struct TreeNode
{
char data;
int value;
TreeNode * leftNode;
TreeNode * rightNode;
TreeNode * parentNode;
char hf01;
};
struct LinkList
{
TreeNode *tn;
LinkList * lk_next;//可以考虑使用*TreeNext
};
LinkList * CreateLinkList(TreeNode * tn)
{
LinkList* l=(LinkList*)malloc(sizeof(LinkList));
l->tn=tn;
l->lk_next=NULL;
return l;
}
LinkList * ConnectLinkList(LinkList * head,LinkList * linkend)
{
LinkList * p=head;
if (p==NULL)
{
return NULL;
}
while (p->lk_next!=NULL)
{
p=p->lk_next;
}
p->lk_next=linkend;
return head;
}
LinkList * DeleteLinkElemNode(LinkList * lk_head)
{
LinkList * head=lk_head->lk_next;
return head;
}
TreeNode * popElemNode(LinkList * lk_head)
{
return lk_head->tn;
}
LinkList * InsertLinkElemNode(LinkList * lk_head,TreeNode * t)
{
LinkList * p=lk_head;
LinkList * pre=NULL;
LinkList * temp= CreateLinkList(t);
if (lk_head==NULL)
{
return temp;
}
while(p!=NULL){
if (t->value<=p->tn->value)
{
if (p==lk_head)//插入在开始
{
lk_head=temp;
temp->lk_next=p;
}
else{//插入在中间
temp->lk_next=p;
pre->lk_next=temp;
}
break;
}
pre=p;
p=p->lk_next;
}
if (p==NULL)//插入在末尾
{
pre->lk_next=temp;
}
return lk_head;
}
TreeNode * CreateBiTree(char d,int v)
{
TreeNode * t=NULL;
t=(TreeNode*)malloc(sizeof(TreeNode));
t->data=d;
t->value=v;
t->leftNode=NULL;
t->rightNode=NULL;
t->hf01='0';
t->parentNode=NULL;
return t;
}
TreeNode * CommNewbBiTree(TreeNode * t1,TreeNode * t2)
{
TreeNode * t=NULL;
t=(TreeNode*)malloc(sizeof(TreeNode));//要检查是否开辟空间成功,这里没处理
t->leftNode=t1;
t->rightNode=t2;
t->value=t1->value + t2->value;
t->data=NULL;
t->parentNode=NULL;
t->hf01='0';
t1->hf01='0';
t2->hf01='1';
t1->parentNode=t;
t2->parentNode=t;
return t;
}
2.源文件
#include "HuffManTree.h"
#include <string.h>
//给定一个字符串,根据字符出现的频率进行哈夫曼编码
//abdsdfdkfdfjkgjkekjrerkekrjerjkrejrelklfdkldf
//asdsfdgweweweew afsdd
struct Letter
{
char data;
int num;
char hfcode[10];//可以装下叶子节点为512,去除最后一个用来放'\0',也可以装下256,ascii表只有180不到,够了。
};
struct Letter l[256];
int letterlen=0;
void TraversBiTree(TreeNode *t)
{
if (t==NULL)
{
return;
}
if (t->data!=NULL)
{
printf("%c : ",t->data);
TreeNode * p=t;
char hfcode[10];
int i=0;
if (p->parentNode==NULL)
{
hfcode[i++]='0';
}
while(p->parentNode!=NULL)
{
hfcode[i++]=p->hf01;
p=p->parentNode;
}
hfcode[i]='\0';
for (int j=0;j<letterlen;j++)
{
//在letter中查找与该叶子节点数据相同的
if (t->data==l[j].data)
{
//拷贝hfcode
int m=0;
for (int k=i-1;k>=0;k--)
{
l[j].hfcode[m++]=hfcode[k];
}
l[j].hfcode[m]='\0';
printf("%s\n",l[j].hfcode);
break;
}
}
}
TraversBiTree(t->leftNode);
TraversBiTree(t->rightNode);
}
void PrintHuffManCode(char arr[],int len)
{
for (int i=0;i<len;i++)
{
for (int j=0;j<letterlen;j++)
{
if (arr[i]==l[j].data)
{
printf("%s",l[j].hfcode);
}
}
}
printf("\n");
}
void HuffManCodeToLetter(char arr[],TreeNode * t)
{
//这里可以检查权值wpl 如果不相等就不要解码了
TreeNode * head=t;
int len=strlen(arr);
int i=0;
while(i<len)
{
while(t->data==NULL && i<len){
if (arr[i]=='0')
{
t=t->leftNode;
}
else
{
t=t->rightNode;
}
i++;
}
printf("%c",t->data);
t=head;
}
}
int main()
{
char arr[101];
int brr[256]={0};
gets(arr);
int len=strlen(arr);
for (int i=0 ;i<len;i++)
{
brr[arr[i]]++;
}
int k=0;//Letter的长度
for (int j=0;j<256;j++)
{
if (brr[j]!=0)
{
l[k].data=j;
l[k++].num=brr[j];
}
}
letterlen=k;
//对Letter根据出现的次数进行排序
for (int i=0;i<k-1;i++)
{
for (int j=i+1;j<k;j++)
{
if (l[i].num>l[j].num)
{
Letter tmp=l[i];
l[i]=l[j];
l[j]=tmp;
}
}
}
//把有效数据加入链表
TreeNode *t_head=CreateBiTree(l[0].data,l[0].num);
TreeNode * t_p=t_head;
LinkList* l_head=CreateLinkList(t_head);
LinkList * l_p=l_head;
for (int i=1 ;i<k;i++)
{
t_p=CreateBiTree(l[i].data,l[i].num);
l_p=CreateLinkList(t_p);
l_head=ConnectLinkList(l_head,l_p);
}
//链表检查是否正确
l_p=l_head;
while(l_p!=NULL){
printf("link -> %c: %d\n",l_p->tn->data,l_p->tn->value);
l_p=l_p->lk_next;
}
l_p=l_head;
//构建哈夫曼树
while (l_p->lk_next!=NULL)
{
TreeNode *a1,*b1,*c1;
a1=popElemNode(l_p);
l_p=DeleteLinkElemNode(l_p);
b1=popElemNode(l_p);
l_p=DeleteLinkElemNode(l_p);
c1= CommNewbBiTree(a1,b1);
l_p=InsertLinkElemNode(l_p,c1);
}
//遍历哈夫曼树,生成哈夫曼编码
TraversBiTree(l_p->tn);
//把字符串转换成哈夫曼编码输出
PrintHuffManCode(arr,len);
//哈夫曼树解码.
char zz[]={'1','0','1','1','0','0','0','1','\0'};
HuffManCodeToLetter(zz,l_p->tn);
getchar();
return 0;
}