哈夫曼编码算法的记录

首先给出构造哈夫曼树的代码

void HufmanCoding(HuffmanTree& HT, int* w,char*l, int n)
/*构造可编码n个元素的哈夫曼树HT,*/
{
	status Select(HuffmanTree & HT, int& s1, int& s2);
	if (n <= 1)return;
	int m = 2 * n - 1;
	HT = (HuffmanTree)malloc((m + 1) * sizeof(HTNote));
	if (!HT)exit(OVERFLOW);
	HuffmanTree p; int i = 1; int s1, s2;
	for (p = HT + 1; i <= n; ++p, ++i, ++w,++l)
	{
		p->letter = *l; p->weight = *w; p->parent = 0; p->lchild = 0; p->rchild = 0;
	};//初始化n个数据//
	for (; i <= m; ++i, ++p) { p->letter = '#'; p->weight = 0; p->parent = 0; p->lchild = 0; p->rchild = 0; }//初始化所有元素//
	for (i = n + 1; i <= m; ++i)//建立哈夫曼树//
	{
		Select(HT, s1, s2);
		HT[s1].parent = i;
		HT[s2].parent = i;
		HT[i].lchild = s1; HT[i].rchild = s2;
		HT[i].weight = HT[s1].weight + HT[s2].weight;
	}
	return;
}

status Select(HuffmanTree& HT, int& s1, int& s2)
/*挑选哈夫曼树表中权值最小的两个点,两两结合*/
{
	HuffmanTree p = HT + 1; int min1, min2;
	while (p->parent) { p++; }
	min1 = p->weight;
	s1 = p - HT;
	p++;
	while (p->parent)p++;
	min2 = p->weight;
	s2 = p - HT;
	if (min1 > min2) {
		int t = 0;
		t = min1; min1 = min2; min2 = t;
		t = s1; s1 = s2; s2 = t;
	}
	while (p->weight) {
		if (min1 > p->weight && !p->parent) {
			min1 = p->weight; s1 = p - HT;
		}
		p++;
	}
	p = HT + 1;
	while (p->weight) {
		if (min2 > p->weight && !p->parent && p - HT != s1) {
			min2 = p->weight; s2 = p - HT;
		}
		p++;
	}
	return ok;
}


在select函数中遇到很多麻烦,s1,s2要赋初值时,就要先检查赋的值是未被选择过的,由于要同时找出数组中的最小值s1和第二小s2,所以先后做两次循坏筛选。(我没有找到可以在一次循坏中一起找到两个数的办法。因为s1,s2可能一开始就赋值最小值,所以无法用记录下s1前一个数来表示s2。)

下面是哈夫曼树生成编码的代码

void encode(HuffmanTree& HT, HuffmanCode& HC,int n)
/*用哈夫曼树生成编码*/
{   
	char* cd = (char*) malloc(n*sizeof(char));
	cd[n-1]='\0';
	HC = (HuffmanCode)malloc( (n+1)*sizeof(char *) );
	if (!HC)exit(Error);
	int i;
	for (i = 1; i <= n; ++i)
	{
		int start = n - 1;
		int c, f;
		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));
		 if (!HC[i])exit(OVERFLOW);
	
		strcpy_s(HC[i], strlen(cd)+1, &cd[start]);
	}

利用哈夫曼树生成编码算法从叶子结点向上找双亲结点,如果是双亲结点的左孩子就纪录‘0’,右孩子就纪录‘1’,直到找到根结点。然后申请一个存放编码的HC[i]的数组指针。
注意:!!
最后strcpy_s中,从cd[start]的位置往后读,不将前面的没有赋值的赋值到HC[i],因为编码的个数是不尽相同的。

然后是销毁哈夫曼树的代码

void DestroyTree(HuffmanTree& HT)
/*销毁哈夫曼德树*/
{
	if (!HT)return;
	free(HT);
	HT = NULL;
	return;
}

void DestroyCode(HuffmanCode& HC,int n)
{
	
	free(HC); HC = NULL;
	return;
}

销毁HC时
我发现不需要对HC[i]先进行销毁,否则会报错
在这里插入图片描述


最后,记录一个让我耗时很久的低级错误

他是这样报错的
在这里插入图片描述
还有这样报错的
他是这样报错的
还有这样报错的
我挣扎了很久之后发现错在这里

cd[n-1]=char"\0";

我把单引号达成了双引号,然后系统将”\0“看作两个字符,报错溢出

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值