#include <stdio.h> #include <stdlib.h> #include <string.h> #define M 1000 #define N 128 typedef struct node { int weight; struct node *lchild , *rchild , *parent ; struct node *next; }HuffmanNode , *HuffmanTree; typedef struct { char ch; char code[N]; }CodeNode; int n; void Open(char s[]) { FILE *fp; char name[10]; int i=0; printf("请输入你要打开的文件名:"); gets(name); if ((fp = fopen(name,"rt")) == NULL ) { printf("打开文件失败!/n"); exit(1); } s[i++] = fgetc(fp); while(s[i-1] != EOF) s[i++] = fgetc(fp); s[i] = '/0'; printf("读取到的字符:/n"); puts(s); fclose(fp); } void Save(char s[]) { FILE *fp; char name[10]; printf("请输入你要保存的文件名:"); gets(name); if ((fp = fopen(name,"wt")) == NULL) { printf("保存文件失败!/n"); exit(1); } fputs(s,fp); fclose(fp); } void SearchStr(char s[] , char str[] , int count[]) { int i , j , k=0; for (i=0 ; i<N ; i++) count[i] = 0; for (i=0 ; s[i] ; i++) { for (j=0 ; j<k ; j++) { if (str[j] == s[i]) { count[j]++; break; } } if (j == k) { str[k] = s[i]; count[k]++; k++; } } str[k-1] = '/0'; n = k-1; } void SelectMin(HuffmanTree HT , int k , HuffmanTree *HT1 , HuffmanTree *HT2) { int i , min; HuffmanTree p; min = 3128; for ( p=HT,i=0 ; i<k ; i++,p=p->next) { if (p->weight<min && p->parent == NULL) { min = p->weight; *HT1 = p ; } } min = 3128; for ( p=HT,i=0 ; i<k ; i++,p=p->next) { if (p->weight<min && p->parent == NULL && p!=*HT1) { min = p->weight; *HT2 = p ; } } } void CreatHuffmanTree(HuffmanTree *HT , int count[]) { int i; HuffmanTree p , HT1 , HT2; p = *HT = (HuffmanTree)malloc(sizeof(HuffmanNode)); p->next = p->lchild = p->rchild = p->parent = NULL; for (i=0 ; i<2*n-1 ; i++) { p->next = (HuffmanTree)malloc(sizeof(HuffmanNode)); p = p->next; p->next = p->lchild = p->rchild = p->parent = NULL; } for ( p=*HT ,i=0 ; i<n ; i++) { p->weight = count[i]; p = p->next; } for (i=n ; i<2*n-1 ; i++) { SelectMin(*HT,i,&HT1,&HT2); HT1->parent = HT2->parent = p; p->lchild = HT1; p->rchild = HT2; p->weight = HT1->weight + HT2->weight; p = p->next; } free(p); } void CodeHuffman(HuffmanTree HT , CodeNode HC[] , char str[]) { int i , j , k , x; char ch; HuffmanTree p , q=HT; for (i=0 ; i<n ; i++) HC[i].ch = str[i]; for (i=0 ; i<n ; i++) { j = 0; x = 0; for ( p=q; p->parent ; p=p->parent) { if (p == p->parent->lchild) HC[i].code[j++] = '0'; else HC[i].code[j++] = '1'; } HC[i].code[j] = '/0'; k = j/2; while(j>k) //编码反转 { ch = HC[i].code[j-1]; HC[i].code[j-1] = HC[i].code[x]; HC[i].code[x] = ch ; j--; x++; } q = q->next; } } void ToltalCoding(CodeNode HC[] , char s[] , char code[]) { int i , j ; code[0] = '/0'; for (i=0 ; s[i] ; i++) { for (j=0 ; j<n ; j++) { if (s[i] == HC[j].ch) strcpy(code+strlen(code),HC[j].code); } } } void Decoding(HuffmanTree HT , char code[] , char str[] , char ss[]) { int i , j , k=0 ; HuffmanTree p , q , root; for (root=HT ; root->parent ; root=root->parent); for (i=0 , p=root ; code[i] ; i++) { if (code[i] == '0') p = p->lchild; else p = p->rchild; if (p->lchild==NULL && p->rchild==NULL) { for (j=0,q=HT ; q!=p ; q=q->next,j++); ss[k++] = str[j]; p = root; } } ss[k] = '/0'; printf("解码结果:/n"); puts(ss); } void main(void) { int i = 0; // char xuanzhe; char s[M],ss[M]; //定义字符串数组,s[]存放将要编码的字符串,ss[]存解码后的字符串 char str[N]; //存放输入的字符串中n个不同的字符 int count[N]; //存放n个不同字符对应的在原字符串中出现的次数 char code[M]; //存放最终编码完成后的编码 // char choice; HuffmanTree HT; //定义一个哈夫曼树的链表 CodeNode HC[N]; Open(s); SearchStr(s,str,count); CreatHuffmanTree(&HT,count); CodeHuffman(HT,HC,str); for ( i=0 ; i<n ; i++ ) printf("字符:%c/t权值:%d/t编码:%s/n",str[i],count[i],HC[i].code); ToltalCoding(HC,s,code); Decoding(HT,code,str,ss); free(HT); }