【哈夫曼树】

【哈夫曼树】

当用 n 个结点(都做叶子结点且都有各自的权值)试图构建一棵树时,如果构建的这棵树的带权路径长度最小,称这棵树为“最优二叉树”,有时也叫“赫夫曼树”或者“哈夫曼树”
构建哈夫曼树:
1.在 n 个权值中选出两个最小的权值,对应的两个结点组成一个新的二叉树,且新二叉树的根结点的权值为左右孩子权值的和;
2.在原有的 n 个权值中删除那两个最小的权值,同时将新的权值加入到 n–2 个权值的行列中,以此类推;
3.重复 1 和 2 ,直到所以的结点构建成了一棵二叉树为止,这棵树就是哈夫曼树。
哈夫曼树结点结构:

typedef struct Huffman{
	int weight;//权重 
	int parent,lch,rch;//父结点、左孩子、右孩子在数组中的位置下标
}HTNode,*HuffmanTree;

找到两个最小值:

//HT数组中存放的哈夫曼树,s1和s2传递的是HT数组中权重值最小的两个结点在数组中的位置
void select_Tree(HuffmanTree HT,int n,int &s1,int &s2) 
{
	int min;
	int i;
	//对找到的两个结点比较大小,min2为大的,min1为小的
	printf("select\r\n");
	//找第一个最小值 
	for(i = 1;i <= n;i++)
	{
		if(HT[i].parent == 0)
		{
			min = i;
			break;
		}
	}
	for(i = min+1;i <= n;i++)
	{
		if(HT[i].parent == 0&&HT[i].weight < HT[min].weight )
		{
			min = i;
		}
	}
	s1 = min;
	printf("s1 = %d\n",s1);
	//找第二个最小值
	for(i = 1;i <= n;i++)
	{
		if(HT[i].parent == 0&&i != s1)
		{
			min = i;
			break;
		}
	} 
	for(i = min+1;i <= n;i++)
	{
		if(HT[i].parent == 0 && HT[i].weight <= HT[min].weight && min != s1)
		{
			min = i;
		}
	}
	s2 = min;
	printf("s2 = %d\n",s2);
}

创建哈夫曼树:

//HT为地址传递的存储哈夫曼树的数组,n为结点个数
void creat_Tree(HuffmanTree HT,int n)
{
	int m,i;
	int s1,s2;
	printf("creat\r\n");
	
	if(n <= 1)
	{
		return;// 如果只有一个编码就相当于0
	}
	
	m = 2*n - 1;//数组一共有2n-1个元素;
	HT = (HuffmanTree)calloc(m+1,sizeof(Huffman));// 0号位置不用
	
	for(i = 1;i <= m ;i++)
	{
		HT[i].lch = 0;
		HT[i].rch = 0;
		HT[i].parent = 0;
	} 
	
	printf("in weight\n");
	for(i = 1;i<=n;i++)
	{
		std::cin>>HT[i].weight ;
	}//输入权重
	
	printf("111\r\n");
	for(i = n+1;i <= m;i++)//合并产生n-1个节点-构造哈夫曼树 
	{
		select_Tree(HT,i-1,s1,s2);//在ht[k](1<=k<=i-1),找最小且双亲域为0的两个节点,返回它们在ht中的序号 
		
		HT[i].weight = HT[s1].weight + HT[s2].weight ;//i的权值为s1和s2之和 
		HT[s1].parent = i;
		HT[s2].parent = i;//从ht中删除s1和s2 
		HT[i].lch = s1;
		HT[i].rch = s2;
		printf("HT[%d].weight = %d,HT[%d].weight = %d\r\n",s1,HT[s1].weight,s2,HT[s2].weight );
		printf("end of %d\r\n HT[%d].weight = %d\r\n",i,i,HT[i].weight );
	} 
	printf("哈夫曼树为:>\n");
	printf("下标   权值     父结点   左孩子   右孩子\n");
	printf("0                                  \n");
	for (int i = 1; i <= m; i++)
	{
		printf("%-4d   %-6d   %-6d   %-6d   %-6d\n", i, HT[i].weight, HT[i].parent, HT[i].lch, HT[i].rch);
	}
	printf("\n");
}

总代码:

#include <stdio.h>
#include <malloc.h>
#include <iostream>
//哈夫曼树结点结构
typedef struct Huffman{
	int weight;//权重 
	int parent,lch,rch;//父结点、左孩子、右孩子在数组中的位置下标
}HTNode,*HuffmanTree;
//HT数组中存放的哈夫曼树,s1和s2传递的是HT数组中权重值最小的两个结点在数组中的位置
void select_Tree(HuffmanTree HT,int n,int &s1,int &s2) 
{
	int min;
	int i;
	//对找到的两个结点比较大小,min2为大的,min1为小的
	printf("select\r\n");
	//找第一个最小值 
	for(i = 1;i <= n;i++)
	{
		if(HT[i].parent == 0)
		{
			min = i;
			break;
		}
	}
	for(i = min+1;i <= n;i++)
	{
		if(HT[i].parent == 0&&HT[i].weight < HT[min].weight )
		{
			min = i;
		}
	}
	s1 = min;
	printf("s1 = %d\n",s1);
	//找第二个最小值
	for(i = 1;i <= n;i++)
	{
		if(HT[i].parent == 0&&i != s1)
		{
			min = i;
			break;
		}
	} 
	for(i = min+1;i <= n;i++)
	{
		if(HT[i].parent == 0 && HT[i].weight <= HT[min].weight && min != s1)
		{
			min = i;
		}
	}
	s2 = min;
	printf("s2 = %d\n",s2);
}
//HT为地址传递的存储哈夫曼树的数组,n为结点个数
void creat_Tree(HuffmanTree HT,int n)
{
	int m,i;
	int s1,s2;
	printf("creat\r\n");
	
	if(n <= 1)
	{
		return;// 如果只有一个编码就相当于0
	}
	
	m = 2*n - 1;//数组一共有2n-1个元素;
	HT = (HuffmanTree)calloc(m+1,sizeof(Huffman));// 0号位置不用
	
	for(i = 1;i <= m ;i++)
	{
		HT[i].lch = 0;
		HT[i].rch = 0;
		HT[i].parent = 0;
	} 
	
	printf("in weight\n");
	for(i = 1;i<=n;i++)
	{
		std::cin>>HT[i].weight ;
	}//输入权重
	
	printf("111\r\n");
	for(i = n+1;i <= m;i++)//合并产生n-1个节点-构造哈夫曼树 
	{
		select_Tree(HT,i-1,s1,s2);//在ht[k](1<=k<=i-1),找最小且双亲域为0的两个节点,返回它们在ht中的序号 
		
		HT[i].weight = HT[s1].weight + HT[s2].weight ;//i的权值为s1和s2之和 
		HT[s1].parent = i;
		HT[s2].parent = i;//从ht中删除s1和s2 
		HT[i].lch = s1;
		HT[i].rch = s2;
		printf("HT[%d].weight = %d,HT[%d].weight = %d\r\n",s1,HT[s1].weight,s2,HT[s2].weight );
		printf("end of %d\r\n HT[%d].weight = %d\r\n",i,i,HT[i].weight );
	} 
	printf("哈夫曼树为:>\n");
	printf("下标   权值     父结点   左孩子   右孩子\n");
	printf("0                                  \n");
	for (int i = 1; i <= m; i++)
	{
		printf("%-4d   %-6d   %-6d   %-6d   %-6d\n", i, HT[i].weight, HT[i].parent, HT[i].lch, HT[i].rch);
	}
	printf("\n");
}

int main()
{
	int n;
	HuffmanTree HT;
	printf("请输入数据个数:\r\n");
	scanf("%d",&n); 
	creat_Tree(HT,n);
}

运行结果:

请输入数据个数:
5
creat    
in weight
1 5 7 2 10
111   
select
s1 = 1
s2 = 4
HT[1].weight = 1,HT[4].weight = 2
end of 6
 HT[6].weight = 3
select
s1 = 6
s2 = 6
HT[6].weight = 3,HT[6].weight = 3
end of 7
 HT[7].weight = 6
select
s1 = 2
s2 = 7
HT[2].weight = 5,HT[7].weight = 6
end of 8
 HT[8].weight = 11
select
s1 = 3
s2 = 5
HT[3].weight = 7,HT[5].weight = 10
end of 9
 HT[9].weight = 17
哈夫曼树为:>
下标   权值     父结点   左孩子   右孩子
0
1      1        6        0        0     
2      5        8        0        0
3      7        9        0        0
4      2        6        0        0
5      10       9        0        0
6      3        7        1        4
7      6        8        6        6
8      11       0        2        7
9      17       0        3        5

在构建哈弗曼树时,要使树的带权路径长度最小,只需要遵循一个原则,那就是:权重越大的结点离树根越近。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
哈夫曼树(Huffman Tree)是一种特殊的二叉树,用于数据压缩和编码。它的构建过程是根据字符出现的频率来确定每个字符的编码,使得出现频率高的字符具有较短的编码,而出现频率低的字符具有较长的编码。 以下是一个Python实现的哈夫曼树的例子: ```python class TreeNode: def __init__(self, value, freq): self.value = value self.freq = freq self.left = None self.right = None def build_huffman_tree(char_freq): nodes = [TreeNode(char, freq) for char, freq in char_freq.items()] while len(nodes) > 1: nodes = sorted(nodes, key=lambda x: x.freq) left_node = nodes.pop(0) right_node = nodes.pop(0) parent_node = TreeNode(None, left_node.freq + right_node.freq) parent_node.left = left_node parent_node.right = right_node nodes.append(parent_node) return nodes[0] def encode_huffman_tree(root, code='', codes={}): if root is None: return if root.value is not None: codes[root.value] = code encode_huffman_tree(root.left, code + '0', codes) encode_huffman_tree(root.right, code + '1', codes) return codes def decode_huffman_tree(root, encoded_text): decoded_text = '' current_node = root for bit in encoded_text: if bit == '0': current_node = current_node.left else: current_node = current_node.right if current_node.value is not None: decoded_text += current_node.value current_node = root return decoded_text # 示例用法 char_freq = {'a': 5, 'b': 9, 'c': 12, 'd': 13, 'e': 16, 'f': 45} huffman_tree = build_huffman_tree(char_freq) huffman_codes = encode_huffman_tree(huffman_tree) encoded_text = ''.join([huffman_codes[char] for char in 'abcdef']) decoded_text = decode_huffman_tree(huffman_tree, encoded_text) print("Huffman Codes:", huffman_codes) print("Encoded Text:", encoded_text) print("Decoded Text:", decoded_text) ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值