哈夫曼树又称最优二叉树,是带权路径最短的树,可以用来构造最优编码,用于信息传递,数据压缩等方面,是一种应用广泛的二叉树。
哈夫曼算法的实现
(1)存储结构
哈夫曼树是一种二叉树,其有自己的存储特点,可以采用静态三叉链表来实现。对于每个节点,它的存储信息应包含自身的权值,双亲信息,以及左右孩子的信息。因此可以设计成如下所示的三叉链表结点结构。
weight------parent------Lchild------Rchild
类型定义如下
struct huffman {
char n;
int weight;
struct huffman *next;
struct huffman *LChlid,*RChlid,*Parent;
};
(2)哈夫曼算法的实现
对于一串字符串,我们可以统计出串中每个字符出现的次数,以此来表示它们的权值,统计完后把他们的权值依次排序,然后把第一个和第二个进行求和,并且申请空间来存储该节点的信息,该你结点就是权值最小的两个节点的双亲节点,这两个结点就是新申请结点的孩子结点,然后将新结点和后续的结点根据权值的大小放到合适的位置;再找出权值最小的两个结点,直到把权值最大的两个结点处理完毕。至此,把所有的字符根据权值大小存储到相应结点中。这样,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 ++;
}
}