数据结构之Huffman(哈夫曼)树

哈夫曼树

代码自己手撸的 只看了一遍思路 -.- 望指正
思路重现

1.根据给定的n个权值{w1,w2, …wn}构造n棵只有一个叶结点的二叉树,从而得到一个二叉树的集合F = {T1 T2 T3 …Tn}
2.在F中选取根节点的权值最小和次小的两颗二叉树作为左右子树构造一颗新的二叉树,这棵二叉树根节点的权值为其左右子树根节点权值之和。
3.在集合F中删除作为左右子树的两颗二叉树,并将新建的二叉树加入到集合F中
4.重复2.3步骤 直到F只含有一颗二叉树为止,这棵树便是要建立的哈弗曼树

简而言之就是每次找权值最小的两个节点 将其组成一颗二叉树 直到将所有节点达到2n-1个为止
今天从CodeBlocks换成用VS2017 感觉还是VS牛逼!!
/** 规定权值小的为左孩子,权值大的为右孩子*/
#include <stdio.h>
#include <stdlib.h>
#define MAXLEAVES 5  //初始叶子结点数
#define MAXNODE 2*MAXLEAVES - 1 //哈弗曼树的结点总数

/** 规定权值小的为左孩子,权值大的为右孩子*/
typedef struct
{
	int weight; //结点权值
	int parent, left, right;//父节点下标  左右孩子下标
	int flag;//记录该节点是否已经判断过 没有判断过标记为0 判断过标记为1
}HuffNode;

void Init_HuffmanTree(HuffNode HuffArray[], int n);//初始化所有节点
void Create_HuffmanTree(HuffNode HuffArray[]);//根据下标对应权值相加 得到新的权值 并且找到双亲节点
void Show_HuffmanTree(HuffNode HuffArray[], int n);//输出哈夫曼数组
int Select_Sort(HuffNode HuffArray[], int num);//选出权值最小的两个下标

int main()
{
	//分配2n - 1 个结点内存数组
	HuffNode HuffArray[MAXNODE];
	printf("初始化完成的哈夫曼数组:\n");
	Init_HuffmanTree(HuffArray, MAXNODE);
	Show_HuffmanTree(HuffArray, MAXLEAVES);
	printf("构造哈夫曼数组,并输出:\n");
	Create_HuffmanTree(HuffArray);
	Show_HuffmanTree(HuffArray, MAXNODE);

	return 0;
}

/** 初始化哈夫曼数组*/
void Init_HuffmanTree(HuffNode HuffArray[], int n)
{
	int i = 0;
	for (i; i < MAXNODE; i++)//初始化
	{
		HuffArray[i].parent = -1;
		HuffArray[i].left = -1;
		HuffArray[i].right = -1;
		HuffArray[i].flag = 0;
	}
	//为了方便直接给定权值
	HuffArray[0].weight = 28;
	HuffArray[1].weight = 10;
	HuffArray[2].weight = 20;
	HuffArray[3].weight = 7;
	HuffArray[4].weight = 35;

}
/** 创建哈夫曼树*/
void Create_HuffmanTree(HuffNode HuffArray[])
{
	int i = MAXLEAVES;
	int minindex1, minindex2;
	for (i; i < MAXNODE; i++)//确定需要几次大循环
	{
		minindex1 = Select_Sort(HuffArray, i);
		minindex2 = Select_Sort(HuffArray, i);
		HuffArray[i].weight = HuffArray[minindex1].weight + HuffArray[minindex2].weight;
		HuffArray[i].left = minindex1;
		HuffArray[i].right = minindex2;
		HuffArray[minindex1].parent = HuffArray[minindex2].parent = i;
	}
}

void Show_HuffmanTree(HuffNode HuffArray[], int n)
{
	int i = 0;
	printf("下标  权值  双亲下标    左孩子     右孩子		flag\n");
	for (i;i < n;i++)
	{
		printf("%d     %d      %d          %d         %d			%d\n", i, HuffArray[i].weight,
			HuffArray[i].parent,
			HuffArray[i].left,
			HuffArray[i].right,
			HuffArray[i].flag);
	}
}

int Select_Sort(HuffNode HuffArray[], int num)
{
	int m;
	int minIndex;
	for (m = 0;m < num;m++)
	{
		if (HuffArray[m].flag != 1)  // 找的应该是第一个flag不为1的作为最小值 
													// 因为一旦第一个在某次循环中被选中  下一次也就意味着不可再被认为是minindex
		{
			minIndex = m;
			break;
		}
	}
	for (m = 0;m < num;m++)
	{
		if (HuffArray[m].flag != 1)
		{
			if (HuffArray[minIndex].weight > HuffArray[m].weight)
			{
				minIndex = m;
			}
		}
	}
	HuffArray[minIndex].flag = 1;
	return minIndex;
}


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
哈夫曼树是一种带权路径长度最短的二叉,也称为最优二叉。在哈夫曼树中,每个叶子节点都有一个权值,而非叶子节点没有权值。哈夫曼树的构造过程是通过贪心算法实现的,即每次选择权值最小的两个节点合并成一个新节点,直到最后只剩下一个节点为止。哈夫曼树的应用非常广泛,其中最常见的应用是数据压缩。 以下是构造哈夫曼树哈夫曼编码的步骤: 1. 统计每个字符出现的频率,并将它们作为叶子节点的权值。 2. 将所有的叶子节点按照权值从小到大排序。 3. 选择权值最小的两个节点合并成一个新节点,新节点的权值为这两个节点的权值之和。 4. 将新节点插入到原来的节点序列中,并重新按照权值从小到大排序。 5. 重复步骤3和步骤4,直到只剩下一个节点为止,这个节点就是哈夫曼树的根节点。 6. 对于每个叶子节点,从它到根节点的路径上标记0或1,得到每个字符的哈夫曼编码。 以下是Python实现哈夫曼树哈夫曼编码的代码: ```python import heapq from collections import defaultdict def huffman_encoding(data): # 统计每个字符出现的频率 freq = defaultdict(int) for c in data: freq[c] += 1 # 将每个字符作为一个叶子节点,并将它们加入到优先队列中 heap = [[weight, [char, ""]] for char, weight in freq.items()] heapq.heapify(heap) # 合并节点,构造哈夫曼树 while len(heap) > 1: left = heapq.heappop(heap) right = heapq.heappop(heap) for pair in left[1:]: pair[1] = '0' + pair[1] for pair in right[1:]: pair[1] = '1' + pair[1] heapq.heappush(heap, [left[0] + right[0]] + left[1:] + right[1:]) # 得到每个字符的哈夫曼编码 huffman_code = dict(heapq.heappop(heap)[1:]) return huffman_code def huffman_decoding(data, huffman_code): # 将哈夫曼编码转换为反向字典 reverse_code = {v: k for k, v in huffman_code.items()} # 解码数据 current_code = "" decoded_data = "" for bit in data: current_code += bit if current_code in reverse_code: decoded_data += reverse_code[current_code] current_code = "" return decoded_data ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值