#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MY_STRMAX 100
#define infinity 1000000
typedef struct
{
unsigned int weight; //深度
char ch; //结点数值
unsigned int parent; //双亲
unsigned int lchild; //左孩子
unsigned int rchild; //右孩子
}HTNode,*HuffmanTree; //动态分配数组存储赫夫曼树
typedef char **HuffmanCode; //动态分配数组存储赫夫曼编码表
#include "Huffmantree.h"
int Min( HuffmanTree t,int n )
{ /* 返回i个结点中权值最小的树的根结点序号,函数select()调用 */
int i,flag;
unsigned int f = infinity; // 取f为不小于可能的值
for(i = 1;i <= n; i++)
if( t[i].weight < f && t[i].parent == 0 ) // t[i]是树的根结点
f = t[i].weight,flag = i;
t[flag].parent = 1; // 给选中的根结点的双亲赋1,避免第2次查找该结点
return flag;
}
void Select( HuffmanTree *t,int n,int *s1,int *s2 )
{ /* 在i个结点中选择2个权值最小的树的根结点序号,s1为其中序号小的那个 , s2为其中序号次小的那个 */
int x;
*s1=Min(*t,n);
*s2=Min(*t,n);
if((*t)[*s1].weight > (*t)[*s2].weight )
{
x = *s1;
*s1 = *s2;
*s2 = x;
}
}
void HuffmanCoding(HuffmanTree *HT,HuffmanCode *HC,int *w,int n)
{ /*w存放n个字符的权值(均>0),构造赫夫曼树HT,并求出n个字符的赫夫曼编码HC */
int m,i,s1,s2,start,num=0;
unsigned int c,f;
HuffmanTree p;
char *cd;
if(n<=1)
return;
m=2*n-1; //开辟的空间 比元素个数多 因为后续生成的新子树要用到
*HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode)); /* 0号单元未用 */
for(p=*HT+1,i=1;i<=n;++i,++p,++w,++num)//初始化n个叶子结点
{
(*p).weight=*w;
//这部分是给确定的子树赋值,包括字母A-Z权值从数组中得出
(*p).parent=0;
(*p).lchild=0;
(*p).rchild=0;
}
for(;i<=m;++i,++p)
(*p).parent=0;
for(i=n+1;i<=m;++i) /* 建赫夫曼树 */
{ //在HT[1~i-1]中选择parent为0且weight最小的两个结点,其序号分别为s1和s2
Select(HT,i-1,&s1,&s2);
(*HT)[s1].parent=(*HT)[s2].parent=i; //这部分给后面要用到的新节点 初值
(*HT)[i].lchild=s1;
(*HT)[i].rchild=s2;
(*HT)[i].weight=(*HT)[s1].weight+(*HT)[s2].weight;
}
//赫夫曼编码的求出,保存在HC里面(二维数组)
// 从叶子到根逆向求每个字符的赫夫曼编码
*HC=(HuffmanCode)malloc((n+1)*sizeof(char*));
// 分配n个字符编码的头指针向量([0]不用)
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);
//释放工作空间
}
#include "Huffmantree.h"
int main()
{
HuffmanTree HT;
HuffmanCode HC;
int *w,n,i;
printf("请输入叶子结点的个数:");
scanf("%d",&n);
w = (int*)malloc(sizeof(int));
for(i = 0;i < n;i++)
{
printf("请输入第%d个结点的权值:",i+1);
scanf("%d",w+i);
}
for(i = 1;i <= n;i++)
{
printf("哈夫曼编码:");
puts(HC[i]);
}
for(i = 0;i <= n;i++)
{
free(HC[i]);
}
free(HC);
free(HT);
return 0;
}
哈弗曼编码
最新推荐文章于 2023-11-11 17:09:02 发布