编码
给每一个对象标记一个二进制位串来表示一组对象。
例如:ASCII,指令系统
编码分类
- 等长编码:表示一组对象的二进制位串的长度相等。
- 不等长编码:表示一组对象的二进制位串的长度不相等。
前缀编码
前缀编码:一组编码中任一编码都不是其它任何一个编码的前缀。(保证解码时不会有多种可能性)
例题加代码
我们假设给每个字母分配权值:a:45,b:13,c:12,D:16,e:9,f:5,首先按照它们的权值进行构造哈夫曼树
将所有权值左分支改为0,右分支改为1. 就是前缀。
源文件
#include<stdio.h>
#include<stdlib.h>
#include"HuffmanTree.h"
//哈夫曼编码方案:从叶子结点到根结点逆向求每个字符的哈夫曼编码
//参数:已创建的哈夫曼树,存储哈夫曼编码的数组,n为叶子结点个数
void huffmanCoding(struct element huffTree[],char*** huffCode,int n)
{
*huffCode =(char**)malloc(n*sizeof(char*));
//定义工作空间,存储临时产生的编码串
char temp[n];
temp[n-1]='\0';
//遍历哈夫曼树数组,生成哈夫曼编码
int i,start,pos,parent;
for(i=0;i<n;i++)
{
start = n-1;
pos = i;
//找到父结点
parent = huffTree[i].parent;
while(parent!=-1)//父结点不是根结点
{
//判断是左孩子还是右孩子
if(huffTree[parent].lchild == pos)
temp[--start] = '0';
else
temp[--start] = '1';
//当前位置移动到父结点
pos = parent;
//更新父结点
parent = huffTree[parent].parent;
}
//n-1-start+1=n-start为数组长度(有'\0')
(*huffCode)[i] = (char*)malloc((n-start)*sizeof(char));
int j;
for(j=0;j<n-start;j++)
(*huffCode)[i][j]=temp[start+j];
puts((*huffCode)[i]);
}
}
int main()
{
int n=1;
printf("请输入结点个数:");
scanf("%d",&n);
printf("请输入%d个权值:",n);
int w[n];
int i;
for(i=0;i<n;i++)
scanf("%d",&w[i]);
struct element huffTree[2*n-1];
HuffmanTree(huffTree,w,n);
puts("哈夫曼编码如下:");
char**huffCode;
huffmanCoding(huffTree,&huffCode,n);
system("pause>nul");
return 0;
}
HuffmanTree.h文件
#include<stdio.h>
#include<stdlib.h>
struct element
{
int weight;//权重
int parent,lchild,rchild;//双亲,孩子 保存的是下标
};
void select(struct element huffTree[],int n,int* min,int* mi)
{
int tw[n];
int tn[n];
int i,k,j=0;
for(i=0;i<n;i++)
{
if(huffTree[i].parent==-1)
{
tn[j]=i;
tw[j]=huffTree[i].weight;
j++;
}
}
int t;
for(i=0;i<j-1;i++)
for(k=0;k<j-1-i;k++)
{
if(tw[k]>tw[k+1])
{
t=tw[k];
tw[k]=tw[k+1];
tw[k+1]=t;
t=tn[k];
tn[k]=tn[k+1];
tn[k+1]=t;
}
}
*min=tn[0];
*mi=tn[1];
}
void HuffmanTree(struct element huffTree[],int w[],int n)
{
//初始化所有结点的项目为-1
int i,min,mi;
for(i=0;i<2*n-1;i++)
{
huffTree[i].lchild=-1;
huffTree[i].rchild=-1;
huffTree[i].parent=-1;
}
//初始化前n个结点的权值
for(i=0;i<n;i++)
huffTree[i].weight=w[i];
for(i=n;i<2*n-1;i++)
{
select(huffTree,i,&min,&mi);
printf("最小下标:%d,次小下标:%d\n",min,mi);
huffTree[i].weight=huffTree[min].weight+huffTree[mi].weight;
huffTree[min].parent=i;
huffTree[mi].parent=i;
huffTree[i].lchild=min;
huffTree[i].rchild=mi;
}
}