数据结构:霍夫曼(哈夫曼)编码(C语言)

目录

目的:

编码过程:

图示过程说明:

整体代码:

相关小知识点:

运行结果:


 

目的:

掌握霍夫曼树的生成算法

熟练掌握霍夫曼编码的方法

编码过程:

A.首先输入n个待编码的字符data及其权值weight,并将n个字符的权值放入到霍夫曼树的节点中。

B.用select函数遍历n个字符,找出权值最小的两个S1和S2,构造一个新的节点Hi,将S1和S2连接到Hi的lchild和rchild节点上, Hi节点的weight为S1和S2的weight之和。

C.将新建立的节点Hi替换S1和S2,继续步骤B(这时的字符数为n-i,i=1,2,…),直到只剩下一个节点为止。至此,霍夫曼树构造完成。

D.给霍夫曼树HT分配编码,并输出。

图示过程说明:

整体代码:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

typedef struct{
int weight;                //权值
int parent,lchild,rchild;  //双亲以及左右孩子
}HTNode,*HuffmanTree;  //动态分配数组存储霍夫曼树

typedef char* *HuffmanCode;//动态分配数组存储霍夫曼编码

//选择出最小的两个结点
void select(HuffmanTree &HT,int k,int &s1,int &s2){
     int i;
     i=1;
     while(i<=k && HT[i].parent!=0)i++;
     //s1指向最小结点
     s1=i;    
     for(i=1;i<=k;i++)
     {       
         if(HT[i].parent==0&&HT[i].weight<HT[s1].weight)s1=i;
     }
     //s2指向次小结点
     for(i=1;i<=k;i++)
     {
         if(HT[i].parent==0&&i!=s1)
			 break;
     }
     s2=i;  
     for(i=1;i<=k;i++)
     {
     if(HT[i].parent==0&&i!=s1&&HT[i].weight<HT[s2].weight)
		 s2=i;
     }

}

//构建霍夫曼树
void HuffmanCoding(HuffmanTree &HT,HuffmanCode &HC,int *w,int n){
 int m,c,f,s1,s2,i,start;
     char *cd;
     if(n<=1)return;
     m=2*n-1;        //n个叶子结点,n-1个非叶子结点
	 HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode));  //预分配m+1个单元,0号单元未用
     HuffmanTree p=HT+1; 
     w++;   //w从1号开始
     for(i=1;i<=n;i++,p++,w++)	//对n个叶子结点赋初值
     {
         p->weight=*w;
         p->parent=p->rchild=p->lchild=0;
     }
     for(;i<=m;++i,++p)			//对另外n-1个叶子结点赋初值
     {
         p->weight=p->parent=p->rchild=p->lchild=0;
     }
 
     for(i=n+1;i<=m;i++)
     {
		 select(HT,i-1,s1,s2);   //选出当前权值最小的两个结点s1和s2
         HT[s1].parent=i;		 //修改结点s1的双亲值
         HT[s2].parent=i;		 //修改结点s2的双亲值
         HT[i].lchild=s1;		 //修改双亲结点的左孩子结点
         HT[i].rchild=s2;		 //修改双亲结点的右孩子结点
         HT[i].weight=HT[s1].weight+HT[s2].weight;  //修改双亲结点的权值
     }
   //从叶子到根逆向求每个字符的霍夫曼编码
     HC=(HuffmanCode)malloc((n+1)*sizeof(char*)); //分配n个字符编码的头指针变量
     cd=(char*)malloc(n*sizeof(char));   //分配求编码的工作空间
     cd[n-1]='\0';//编码结束符
     for(i=1;i<=n;i++)   //逐个字符求霍夫曼编码
     {   
         start=n-1;            //编码结束符位置
         for(c=i,f=HT[i].parent;f!=0;c=f,f=HT[f].parent)    //从叶子到根逆向求编码
         {   
              if(HT[f].lchild==c) cd[--start]='0';
              else
                   cd[--start]='1';
         }
     HC[i]=(char*)malloc((n-start)*sizeof(char)); //为第i个字符编码分配空间
     strcpy(HC[i],&cd[start]);//从cd复制编码到HC
     }
  free(cd);   //释放工作空间
}


void main(){
int n,i;
int* w;//记录权值
char* ch;//记录字符
HuffmanTree HT;
HuffmanCode HC;
printf("请输入你要进行编码的字符个数");
scanf("%d",&n);
w=(int*)malloc((n+1)*sizeof(int));//记录权值,0号单元未用
ch=(char*)malloc((n+1)*sizeof(char));//记录字符,0号单元未用
printf("依次输入待编码的字符和权值:");
for(i=1;i<=n;i++){
printf("data[%d]=",i);
scanf("%s",&ch[i]);
printf("weight[%d]=",i);
scanf("%d",&w[i]);
}

HuffmanCoding(HT,HC,w,n);
for(i=1;i<=n;i++)
printf("%c:%s\n",ch[i],HC[i]);

}

 

相关小知识点:

char* *HuffmanCode 等价于 char* HuffmanCode[];

strcpy(s1,s2); strcpy函数的意思是:把字符串s2拷贝到s1中,连同字符串结束标志也一同拷贝。如果s2="china",那么s1中存放的是china\0。

运行结果:

学生党,有什么不对的地方请大佬们指出!

  • 2
    点赞
  • 54
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

九洲带鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值