哈弗曼树的编码

来源:互联网 发布:kali linux不能上网 编辑:程序博客网 时间:2024/05/29 16:44

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 afsddstruct 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){//拷贝hfcodeint 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;}



1 0
原创粉丝点击