哈夫曼编码及译码

# 哈夫曼编码

哈夫曼树构造过程:

  1. 在 n 个权值中选出两个最小的权值,对应的两个结点组成一个新的二叉树,且新二叉树的根结点的权值为左右孩子权值的和;
  2. 在原有的 n 个权值中删除那两个最小的权值,同时将新的权值加入到 n–2 个权值的行列中,以此类推;
  3. 重复 1 和 2 ,直到所以的结点构建成了一棵二叉树为止,这棵树就是哈夫曼树。

哈弗曼树编码及译码关键函数如下:

1、哈弗曼树构造函数

//创建哈弗曼树
void createhuff(huff &ht,int n,int *f)
{
	int s1,s2;
	if(n<=1)return;
	int m=2*n-1;
	ht=new htnode[m+1];
	for(int i=1; i<=m; ++i)
	{
		ht[i].parent=0;
		ht[i].lchild=0;
		ht[i].rchild=0;
	}
	for(int i=1; i<=n; i++)
	{
		ht[i].weigth=f[i-1];
	}
	for(int i=n+1; i<=m; ++i)
	{
		select(ht,i-1,s1,s2);
		ht[s1].parent=i;
		ht[s2].parent=i;
		ht[i].lchild=s1;
		ht[i].rchild=s2;
		ht[i].weigth=ht[s1].weigth+ht[s2].weigth;
	}
}

2、哈夫曼编码

//哈夫曼编码
typedef char **huffcode;
void createhuffcode(huff ht,huffcode &hc,int n)
{
	hc=new char*[n+1];
	char cd[n];
	cd[n-1]='\0';
	for(int i=1; i<=n; i++)
	{
		int start=n-1;
		int c=i;
		int f=ht[i].parent;
		while(f!=0)
		{
			--start;
			if(ht[f].lchild==c)
				cd[start]='0';
			else
				cd[start]='1';
			c=f;
			f=ht[f].parent;
		}
		hc[i]=new char[n-start];
		strcpy(hc[i],&cd[start]);

	}
}

3、选择两个最小值函数:select函数

//select算法
void select(huff &HT,int n,int &s1,int &s2)
{
	int minum;
	for(int i=1; i<=n; i++)
	{
		if(HT[i].parent == 0)
		{
			minum = i;
			break;
		}
	}
	for(int i=1; i<=n; i++)
	{
		if(HT[i].parent == 0)
			if(HT[i].weigth <= HT[minum].weigth)
				minum = i;
	}
	s1 = minum;
	for(int i=1; i<=n; i++)
	{
		if(HT[i].parent == 0 && i != s1)
		{
			minum = i;
			break;
		}
	}
	for(int i=1; i<=n; i++)
	{
		if(HT[i].parent == 0 && i != s1)
			if(HT[i].weigth <= HT[minum].weigth)
				minum = i;
	}
	s2 = minum;
}

4、求结点权重

//求权重
void getFrequency(char *ch,int *f)
{
	f[58]= {0};
	for(int i=0; i<strlen(ch); i++)
	{
		int num=ch[i]-'A';
		f[num]++;

	}
	//求哈夫曼结点数
	for(int i=0; i<58; i++)
	{
		if(f[i]!=0)
			len++;
	}
}

5、  哈夫曼译码

//哈夫曼译码
void HuffmanDecoding(huff HT, char *a, char *cha, char *b, int n)
{
	//a用来传入二进制编码,b用来记录译出的字符,cha是与哈夫曼树的叶子对应的字符,n是字符个数相当于cha数组的长度
	int q = 2 * n-1;  //q初始化为根结点的下标
	int k = 0;  //记录存储译出字符数组的下标
	for (int i = 0; i<strlen(a); i++)
	{
		if (a[i] == '0')
		{
			q = HT[q].lchild;
		}
		else if (a[i] == '1')
		{
			q = HT[q].rchild;
		}
		if (HT[q].lchild == 0 && HT[q].rchild == 0)
		{
			b[k++] = cha[q-1];
			q = 2 * n-1;
		}
	}
	b[k] = '\0';
}

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值