数据结构14:哈夫曼树的创建和编码

摘要: 哈夫曼树是十分重要的,常用于压缩的编码和解码。但写起来也比较折磨。

迟到的代码,实在抱歉。上代码!
一.代码块

其实由于哈夫曼树结点的度要么为0,要么为2,并且输入的编码的元素必为
叶节点,所以n个元素也就是n个叶节点的哈夫曼树必为2n-1个总结点。知道了结点个数,我们肯定更喜欢用顺序存储(数组)来存储哈夫曼树,而孩子和双亲则类似于静态链表,用下标代替地址
1)结构体定义

typedef struct huffmanTree
{
   
	char data;
	int weight;
	int lchild,rchild,parent;
}HTNode,*huffmanTreePtr;

typedef char **huffmanTreeCode;//这个其实就是把char** 这个二维数组换成这个名字

2)选取最小的两个权重

由于我们每一次都选用最小的两个值来构建他们的双亲,所以这个函数就是选择从1到length里面最小的两个,用min1和min2传出来。注意,c语言不支持函数传入变量地址,但是c++支持,所以这个虽然用c写的,但是后缀需要是cpp。

void select(huffmanTreePtr &HT,int length,int &min1,int &min2)
{
   
	//这里的tool就是用来找到最小元素的 
	int i,tool = 100000;
	//记录最小的那一个
	for(i = 1;i <= length;i ++)
	{
   
		//只能选择没有双亲的,即没被选过的 
		if(HT[i].weight < tool && HT[i].parent == 0)
		{
   
			tool = HT[i].weight;
			min1 = i;
		}
	}
	
	//记录第二小的那一个
	tool = 100000;
	for(i = 1;i <= length;i ++)
	{
   
		//i不等于于min1代表把第一遍选出的最小元素剔除了 
		if(HT[i].weight < tool && HT[i].parent == 0 && i != min1)
		{
   
			tool = HT[i].weight;
			min2 = i;
			
		}
	}
}

3)创建哈夫曼树
我们输入的数据必为树的叶结点,并且我们是用他们往上去构建树,所以我们先直接把叶结点存在数组1-n的位置。虽然本质上是哈夫曼树,但对于计算机,他就是一个结构体的数组,对我们来说该如何体现树的结构性呢,就是用结构体里面的孩子和双亲代表下标来将他们链接起来。

void createHT(huffmanTreePtr &HT,char *dataArray,int *weightArray,int n)
{
   
	
	int i;
	
	//用来记录下标 
	int min1,min2;
	
	/*为了方便,我们不用数组的第0个元素,所以申请2n个空间*/
	HT = (huffmanTreePtr)malloc(2*n*sizeof(HTNode));
	
	/*对于叶节点,我们将其全部放在数组前n个里面,后面n-1个用来放合成的结点*/
	for(i = 1; i <= n;i ++)
	{
   
		HT[i].data = dataArray[i-1];
		HT[i].weight = weightArray[i-1];
	}
	
	//由于数组0号我们没有用,所以将他们全部初始化为0,代表没有 
	for(i = 0;i < 2*n;i ++)
	{
   
		HT[i].lchild = 0;
		HT[i].rchild = 0;
		HT[i].parent  = 0;
	} 
	
	//这里是开始给后面n-1个合成的元素找双亲和孩子 
	for(i = n+1;i < 2*n;i ++)
	{
   
		select(HT,i-1,min1,min2); 
		HT[i].weight = HT[min1].weight + HT[min2].weight;
		HT[i].lchild = min1;
		HT[i].rchild = min2;
		HT[min1].parent = i;
		HT[min2].parent = i;
	}
	
}

4)创建每个元素的编码

huffmanTreeCode就是一个二维数组,里面每一个元素都是存放编码的数组

我们用的办法是从叶结点网上回溯到根节点,所以得到的编码是逆序的,我们就用一个临时数组存放编码,如果他是双亲的左孩子,就在临时数组的倒数的二个位置(倒数第一个位置为结束符’\0’)赋0,如果是右孩子就赋1。再想上回溯,给倒数第三个位置赋值,一直到根节点。

最后再

  • 19
    点赞
  • 97
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
哈夫曼树是一种可以用来压缩数据的数据结构,它可以生成哈夫曼编码,从而实现对数据的高效压缩和解压缩。下面是一个简单的C语言实现。 首先,我们需要定义一个哈夫曼树节点的结构体: ```c struct huffman_node { char data; // 数据 int weight; // 权重 struct huffman_node *left; // 左子节点 struct huffman_node *right; // 右子节点 }; ``` 接下来,我们需要实现一个函数来创建哈夫曼树。该函数接受一个字符数组和对应的权重数组作为输入,返回哈夫曼树的根节点。 ```c #include <stdlib.h> struct huffman_node* create_huffman_tree(char data[], int weight[], int n) { // 创建叶子节点 struct huffman_node** nodes = (struct huffman_node**)malloc(sizeof(struct huffman_node*) * n); for (int i = 0; i < n; i++) { nodes[i] = (struct huffman_node*)malloc(sizeof(struct huffman_node)); nodes[i]->data = data[i]; nodes[i]->weight = weight[i]; nodes[i]->left = NULL; nodes[i]->right = NULL; } // 构建哈夫曼树 while (n > 1) { // 找到最小的两个节点 int min1 = 0, min2 = 1; if (nodes[0]->weight > nodes[1]->weight) { min1 = 1; min2 = 0; } for (int i = 2; i < n; i++) { if (nodes[i]->weight < nodes[min1]->weight) { min2 = min1; min1 = i; } else if (nodes[i]->weight < nodes[min2]->weight) { min2 = i; } } // 创建新节点 struct huffman_node* new_node = (struct huffman_node*)malloc(sizeof(struct huffman_node)); new_node->data = 0; new_node->weight = nodes[min1]->weight + nodes[min2]->weight; new_node->left = nodes[min1]; new_node->right = nodes[min2]; // 将新节点插入到数组中 nodes[min1] = new_node; nodes[min2] = nodes[n - 1]; n--; } // 返回根节点 return nodes[0]; } ``` 最后,我们需要实现一个函数来生成哈夫曼编码。该函数接受一个哈夫曼树的根节点作为输入,返回一个指向哈夫曼编码的指针数组。 ```c #include <string.h> void generate_huffman_code(struct huffman_node* root, char* code[], int depth, char buffer[]) { if (!root) { return; } // 处理叶子节点 if (!root->left && !root->right) { buffer[depth] = '\0'; code[root->data] = (char*)malloc(sizeof(char) * (depth + 1)); strcpy(code[root->data], buffer); return; } // 处理左子 buffer[depth] = '0'; generate_huffman_code(root->left, code, depth + 1, buffer); // 处理右子 buffer[depth] = '1'; generate_huffman_code(root->right, code, depth + 1, buffer); } char** get_huffman_code(struct huffman_node* root) { char** code = (char**)malloc(sizeof(char*) * 256); char buffer[256]; generate_huffman_code(root, code, 0, buffer); return code; } ``` 现在,我们可以使用上面的代码来创建一个哈夫曼树,并生成对应的哈夫曼编码如: ```c int main() { char data[] = { 'a', 'b', 'c', 'd', 'e', 'f' }; int weight[] = { 45, 13, 12, 16, 9, 5 }; struct huffman_node* root = create_huffman_tree(data, weight, 6); char** code = get_huffman_code(root); for (int i = 0; i < 256; i++) { if (code[i]) { printf("%c: %s\n", i, code[i]); } } return 0; } ``` 输出结果为: ``` a: 0 b: 101 c: 100 d: 111 e: 1101 f: 1100 ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值