Huffman树总结

感觉这一周在写huffman树的时候,碰到了几个以前没有熟记的知识点,所以就写下这篇文章就当是笔记啦.

  • 数据结构
    二叉树 :书中自定义了一个结构体
typedef struct 
{
    unsigned int weight;
    unsigned int parent, lchild, rchild;
}HTNode,*HuffmanTree;  //动态分配数组存储哈夫曼树

在这里,个人觉得还可以插入一个定义对应字符的ch变量,这样就没必要再单独设置一个字符数组类型的变量。

  • 核心实现函数
void InitHuffmanTree(HuffmanTree *HT, HuffmanCode &HC, int *w, int n)
//w存放n个字符的权值(均>0),构造哈夫曼树HT,并求出n个字符的哈夫曼编码HC。
{
	if (n <= 1)
		return;
	int m ;  //用来表示结点个数
	int s1 ,s2;   //用来当作权值最小的两个结点的下标
	HuffmanTree p;   //用来进行指针的移动
	m = 2 * n - 1;
	*HT = (HuffmanTree)malloc((m + 1) * sizeof(HTNode)); //0号单元未用
	p = *HT + 1;
	(*HT)[0].weight = 0;
	(*HT)[0].parent = 0;
	(*HT)[0].lchild = 0;
	(*HT)[0].rchild = 0;
	int i;
	for (i=1;i <= n;i++, p++, w++)  // 从1号单元开始初始化
	{
		(*p).weight = *w;
		(*p).parent = 0;
		(*p).lchild = 0;
		(*p).rchild = 0;
	}
	for (;i <= m;i++, p++)    //空树
	{
		(*p).weight = 0;
		(*p).parent = 0;
		(*p).lchild = 0;
		(*p).rchild = 0;
	}
	for (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].weight = (*HT)[s1].weight + (*HT)[s2].weight;
	}

}
void select(HuffmanTree HT, int n, int *s1, int *s2)
{
	unsigned int a = 65535, b = 65535;  //表示s1,s2的权值
	int temp, i;
	*s1 = 0;	*s2 = 0;   //对s1,s2初始化
	for (i = 1;i <= n;i++)
	{
		if (HT[i].parent)
			continue;
		if (HT[i].weight < a)
		{
			b = a;
			a = HT[i].weight;
			*s2 = *s1;
			*s1 = i;
		}
		else if (HT[i].weight < b)
		{
			b= HT[i].weight;
			*s2 = i;
		}
	}
	if (a > b)   //保证s1对应的权值小于s2对应的权值
	{
		temp = *s2;
		*s2 = *s1;
		*s1 = temp;
	}
}

该函数的思路是0号单位不用,在1号到n号进行权值的录入,这些单位的双亲和左右孩子都是0。(即没有)而对应字符可以在第0位开始。之后从n+1位到2*n-1位进行哈夫曼树的构建。构建的想法是,在HT[1…i-1]里选择双亲为0,且权值最小的两个单位,其序号分别对应s1和s2,在把他们构造一个新的二叉树,直到i=2n-1。

  1. 如果只有一个或者没有字符,则没有编码的必要,直接return。注意,这里是void类型的函数,return 后面不加东西,表示退出函数。
  2. 设置一个指针p来进行对数据的录入。其实只用*HT也是可以的,但每次进行指针的操作之后,就得进行HT–的循环来回到第一个存储单位,时间复杂度就会大大增加。
  3. 在设置一个指针时,先让指针指向NULL,再将指针赋予其他值。
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值