#include <stdlib.h>
#include <stdio.h>
#include <strings.h>
#define MAXBIT 100
#define MAXVALUE 10000
typedef struct {
int weight;
int parent, lchild, rchild;
char info;
}NTNode,*HuffmanTree;
typedef struct{
int bit[MAXBIT];
//再设置一个start用于表示编码在数组中的起始位置
int start;
}HCodeType,*Hcode;
//创建霍夫曼树
HuffmanTree CreateHT(HuffmanTree HuffNode,int n,char a[],int weight[]){
if(!(HuffNode =(HuffmanTree)malloc((2*n-1)*sizeof(NTNode))))printf("分配空间失败");
int i,j,x1,x2,m1,m2;
for(i=0;i<(2*n-1);i++){
HuffNode[i].parent = -1;
HuffNode[i].weight = -1;
HuffNode[i].lchild = -1;
HuffNode[i].rchild = -1;
}
//输入n个叶子节点的权值
for(i=0;i<n;i++){
HuffNode[i].weight = weight[i];
HuffNode[i].info = a[i];
}
//构建树,生成霍夫曼树得循环n-1次,相当于实现select的部分
for(i=0;i<n-1;i++){
m1=m2=MAXVALUE;//m1始终是最小值,m2是次小值
x1=x2=0;
//找出所有节点中权值最小且没有父节点的根合成树
for(j=0;j<n+i;j++){
if(HuffNode[j].parent==-1&&HuffNode[j].weight<m1){
m2 = m1;
x2 = x1;
m1 = HuffNode[j].weight;
x1 = j;
}else if(HuffNode[j].weight<m2&&HuffNode[j].parent==-1){
m2 = HuffNode[j].weight;
x2 = j;
}
}
//设置找到的两节点新产生节点的信息
HuffNode[n+i].weight = HuffNode[x1].weight + HuffNode[x2].weight;
HuffNode[n+i].lchild = x1;
HuffNode[n+i].rchild = x2;
HuffNode[x1].parent = n+i;
HuffNode[x2].parent = n+i;
}
return HuffNode;
}
void CreateHuffCode(HuffmanTree HuffNode,Hcode HuffCode,char a[],int n){
HCodeType cd;//cd用来临时存储信息
HuffCode = (HCodeType*)malloc((2*n-1)*sizeof(HCodeType));
int i,j,c,p;
for(i=0;i<n;i++){
cd.start=n-1;//编码在bit数组中的开始存储位置,数组最大下标为n-1,霍夫曼树编码是从根到叶子的编码。我们从叶子节点开始所以需要倒着存。
c=i;
p = HuffNode[c].parent;
while(p!=-1){
if(HuffNode[p].lchild==c)
cd.bit[cd.start]=0;//若叶子为双亲的左节点则编码0
else
cd.bit[cd.start]=1;//若叶子为双亲的右节点则编码1
cd.start--;//最后一次运行时start指向存储编码的前一位
c=p;
p=HuffNode[c].parent;
}
for(j=cd.start+1;j<n;j++)
HuffCode[i].bit[j]=cd.bit[j];
HuffCode[i].start=cd.start + 1;//记录编码在数组中开始的位置
}
//输出已经保存好的霍夫曼编码
for (i=0;i<n;i++)
{
printf ("%c's Huffman code is:",a[i]);
for (j=HuffCode[i].start; j < n; j++){
printf ("%d", HuffCode[i].bit[j]);
}
printf ("\n");
}
}
void decoding(char a[],HuffmanTree T,int num){
//num为叶子节点数,ch[]用于存放解码之后的字符,a[]存放要解码的01串
int j=0,p=0;
char ch[100];
int i=0;
while(i<strlen(a)){
p = 2*num-2;
while(T[p].lchild != -1){
if(a[i]=='0'){
p = T[p].lchild;
}else{
p = T[p].rchild;
}
i++;
}
ch[j] = T[p].info;
j++;
}
ch[j] = '\0';
for(int m=0;m<j;m++){
printf("%c",ch[m]);
}
printf("\n");
}
int main(){
HuffmanTree T;
T = NULL;
Hcode M;
M = NULL;
char a[] = {'a','b','c','d','e','f','\0'};//n=6
int weight[] = { 5, 9, 12, 13, 16, 45 };
char c[] = "011110110011011100";
T = CreateHT(T, 6, a, weight);
for(int n=0;n<6;n++){
printf("%c",T[n].info);
}
printf("\n");
CreateHuffCode(T,M,a,6);
decoding(c,T,6);
}
霍夫曼树的编码与解码(c语言版)
最新推荐文章于 2024-04-06 16:02:54 发布