哈夫曼樹又稱最優二叉樹,是帶權路徑最短的樹,可以用來構造最優編碼,用於信息傳遞,數據壓縮等方面,是一種應用廣泛的二叉樹。
哈夫曼算法的實現
(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 ++;
}
}