哈弗曼樹的編碼
阿新 • • 發佈:2019-01-10
1.標頭檔案HuffmanTree.h
2.原始檔#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; }
#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; }