哈夫曼树又称最优二叉树,是带权路径最短的树,可以用来构造最优编码,用于信息传递,数据压缩等方面,是一种应用广泛的二叉树。
哈夫曼算法的实现
(1)存储结构
哈夫曼树是一种二叉树,其有自己的存储特点,可以采用静态三叉链表来实现。对于每个节点,它的存储信息应包含自身的权值,双亲信息,以及左右孩子的信息。因此可以设计成如下所示的三叉链表结点结构。
weight------parent------Lchild------Rchild
类型定义如下
struct huffman { char n; int weight; struct huffman *next; struct huffman *LChlid,*RChlid,*Parent; };
对于一串字符串,我们可以统计出串中每个字符出现的次数,以此来表示它们的权值,统计完后把他们的权值依次排序,然后把第一个和第二个进行求和,并且申请空间来存储该节点的信息,该你结点就是权值最小的两个节点的双亲节点,这两个结点就是新申请结点的孩子结点,然后将新结点和后续的结点根据权值的大小放到合适的位置;再找出权值最小的两个结点,直到把权值最大的两个结点处理完毕。至此,把所有的字符根据权值大小存储到相应结点中。这样,huffman树就创建完毕了。
<pre name="code" class="java">
<pre name="code" class="java">#include<stdio.h> #include<stdlib.h> #include<string.h> #define FULL 100 struct huffman { char n; int weight; char *code; struct huffman *next; struct huffman *LChlid,*RChlid,*Parent; }; struct stack { int cnt; struct huffman *top; }; int sum = 0; char string [FULL] = ""; //存储字符串 struct huffman *create(){ struct huffman *Head; struct huffman *New,*End; char str [FULL] = ""; //存储不同字符 int w[FULL]; //存储权值 int i,j; int n = 0; for(i = 0;i<FULL;i++){ w[i] = 0; } printf("Please Input expressions\n"); gets(string); for(i = 0;i<strlen(string);i++){ for(j = 0;j<i;j++){ if(string[i] == str[j]){ break; } } if(i == j){ str[n] = string[i]; w[n]++; n++; }else{ w[j]++; } } New = End = (struct huffman *)malloc(sizeof(struct huffman)); New->n = str[sum]; New->weight = w[sum]; while(1){ sum++; if(sum == 1){ New->next = NULL; Head = New; End = New; New->LChlid = NULL; New->RChlid = NULL; } else{ New->next = NULL; End->next = New; End = New; New->LChlid = NULL; New->RChlid = NULL; } if(sum == n){ break; } New = (struct huffman *)malloc(sizeof(struct huffman)); New->n = str[sum]; New->weight = w[sum]; } return Head; } print(struct huffman *p){ while(p !=NULL){ if(p->LChlid == NULL && p->RChlid == NULL){ printf("%c\t",p->n); }else{ printf("*\t"); } printf("%d\n",p->weight); p = p->next; } } sort(struct huffman *New){ int j; char k; struct huffman *End; if(New->next != NULL){ while(New->next!=NULL){ End = New->next; while(End!=NULL){ if(New->weight>End->weight){ j = New->weight; New->weight = End->weight; End->weight = j; k = New->n; New->n = End->n; End->n = k; } End = End->next; } New = New->next; } } } struct huffman *findLocal(struct huffman *LChlid,struct huffman *RChlid,int weight){ char k[FULL]; struct huffman *p,*q; struct huffman *t = (struct huffman *)malloc(sizeof(struct huffman)); t->weight = weight; t->LChlid = LChlid; t->RChlid = RChlid; LChlid->Parent = RChlid->Parent = t; t->Parent = NULL; p = RChlid; q = p->next; while(q != NULL){ if(t->weight > q->weight && q->next == NULL){ q->next = t;. t->next = NULL; break; } else if(p->weight >= t->weight && p == RChlid) { RChlid->next = t; t->next = q; break; } else if(t->weight >= p->weight && t->weight <= q->weight){ p->next = t; t->next = q; break; } else{ p = q; q = q->next; } } if(q == NULL){ p->next = t; t->next = NULL; } return RChlid->next; } huffmanCode(struct huffman *p,int n){ struct huffman *q,*s; char *cd = p->code = (char*)malloc(n * sizeof(char)); int i,start = n-1; cd[n-1] = 0; s = q = p; p = p->Parent; while(p != NULL){ start--; if(q == p->LChlid){ cd[start] = '0'; } else{ cd[start] = '1'; } q = p; p = p->Parent; } printf("%c\t",s->n); printf("%d\t",s->weight); for(i = 0;i < n-1;i++){ printf("%c",cd[i]); } printf("\n"); } main(){ struct huffman *Head; struct huffman *p,*q; struct huffman *s,*t; struct stack temp; char *cd; char code[FULL] = ""; int size = 0; int weight; int i = 0,j; Head = p = create(); q = p->next; if(q == NULL){ print(p); return 0; } sort(p); weight = p->weight + q->weight; while(1){ p = findLocal(p,q,weight); if(p->next != NULL){ q = p->next; weight = p->weight + q->weight; } else{ break; } } t = p; print(Head); s = p = Head; printf("字符\t权值\t编码\n"); while(p != NULL){ if(p->LChlid == NULL && p->RChlid == NULL){ while(s != NULL){ s = s->Parent; i++; } huffmanCode(p,i); size++; i = 0; } p = p->next; s = p; } printf("所有字符编码为:\n"); p = Head; for(i = 0;i<strlen(string);i++){ while(1){ if(p->LChlid == NULL && p->RChlid == NULL && string[i] == p->n){ printf("%s",p->code); strcat(code,p->code); break; } p = p->next; } p = Head; } printf("\n"); printf("对应的字符串为:\n"); s = t; i = 0; while(i != strlen(code)){ if(code[i] == '0'){ t = t->LChlid; } else{ t = t->RChlid; } if(t->LChlid == NULL && t->RChlid == NULL){ printf("%c",t->n); t = s; } i ++; } }