哈夫曼树的建立、编码以及WPL值的计算

本文详细介绍了如何使用字符集{A,B,C,D,E,F}

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

假设用于通信的电文由字符集{A,B,C,D,E,F}中的字母构成,这些字母在电文中出现的概率分别为{0.10,0.19,0.20,0.35,0.12,0.04},要求:
1、构造一棵Huffman树,填写下表,要求左结点的权不大于右结点的权
2、在下表中填入各字符的Huffman编码(左分支为”0”,右分支为”1”)
3、求带权路径长度
解析:
1、哈夫曼树的构造
将电文概率由大到小依次排序
0.04,0.10,0.12,0.19,0.20,0.35
将0.04和0.10作为左子树,右子树构成一棵树。
则如图所示:
这里写图片描述
它们根节点之和作为新的结点,删掉刚才两个结点,加入新结点0.14重新由大到小排序
0.12,0.14,0.19,0.20,0.35
将最小的两个结点作为左子树、右子树构成新的树。
如图所示:
这里写图片描述
删掉刚才两个结点,加入新结点0.26,重新排序
0.19,0.20,0.26,0.35
将此时最小的两个结点作为左右子树,建立新的树
如图所示:
这里写图片描述
删掉刚才两个结点,加入新结点0.39,重新排序
0.26,0.35,0.39
将此时最小的两个结点作为左右子树,建立新的树
如图所示:
这里写图片描述
至此只剩下两个结点,构成满足条件的树,如图:
这里写图片描述
2,哈夫曼编码
(菜鸟的自我理解,有错误还希望大家指正)
如图所示:
这里写图片描述
这里附加一个数据结构与算法课本案例

这里写图片描述
3,WPL值的计算
首先给出路径和路径长度的概念,从树中一个结点到另一个结点之间的分支构成这两个结点之间的路径,路径上的分支数目称作路径长度。树的路径长度是从树根到每一结点的路径长度之和。
树的带权路径长度为树中所有叶子结点的带权路径长度之和,通常记作WPL.

带权路径长度 = (0.19 +0. 20 + 0.35) * 2 + 0.12 * 3 + (0.04 + 0.10) * 4 = 2.4

要实现一个简单的哈夫曼编码器,首先需要了解哈夫曼编码的基本原理。哈夫曼编码是一种自底向上的贪心算法,用于构建最优前缀码。以下是使用C语言实现的一个简化版本: ```c #include <stdio.h> #include <stdlib.h> #include <stdbool.h> #include <limits.h> // 结点结构体 typedef struct { int data; int freq; struct node* left; struct node* right; } Node; // 创建一个新的结点 Node* newNode(int data) { Node* newNode = (Node*)malloc(sizeof(Node)); newNode->data = data; newNode->freq = 0; newNode->left = newNode->right = NULL; return newNode; } // 比较两个结点的频率 int compare(const void *a, const void *b) { return ((Node*)a)->freq - ((Node*)b)->freq; } // 插入结点到堆 void insert(Node** heap, Node* newNode) { if (*heap == NULL || ((*heap)->freq <= newNode->freq)) { newNode->left = *heap; *heap = newNode; } else { Node* temp = *heap; while (temp != NULL && newNode->freq < temp->freq) { *heap = temp; temp = temp->left; } newNode->left = temp->left; temp->left = newNode; } } // 构建哈夫曼 Node* buildHuffmanTree(Node** heap) { if (*heap == NULL || (*heap)->left == NULL) return *heap; Node* temp = newNode(0); temp->left = buildHuffmanTree(heap); temp->right = buildHuffmanTree(&(*heap)->left); free(*heap); *heap = temp; return temp; } // 打印哈夫曼编码 void printCodes(Node* root, char* code, int index) { if (root == NULL) return; if (root->left == NULL && root->right == NULL) { printf("%d: %s", root->data, code + index); index += strlen(code + index); printf("\n"); } else { printCodes(root->left, code, index); printCodes(root->right, code, index); } } // 计算每个字符的WPL(Weighted Path Length) double calculateWPL(Node* root) { if (root == NULL) return 0; return root->freq + calculateWPL(root->left) + calculateWPL(root->right); } int main() { // 示例输入:字符及其频率 const char* input = "abracadabra"; int freqs[] = {5, 2, 2, 1, 3, 1, 4, 2, 1}; int numChars = sizeof(freqs) / sizeof(freqs[0]); // 初始化堆 Node* heap[2] = {NULL, NULL}; // 将字符及其频率插入堆 for (int i = 0; i < numChars; i++) { Node* newNode = newNode(i); newNode->freq = freqs[i]; insert(heap, newNode); } // 构建哈夫曼 Node* huffmanRoot = buildHuffmanTree(heap); // 获取哈夫曼编码 char codes[256]; memset(codes, 0, sizeof(codes)); printCodes(huffmanRoot, codes, 0); // 计算WPL double wpl = calculateWPL(huffmanRoot); printf("Weighted Path Length (WPL): %.2f\n", wpl); return 0; } ``` 这个程序首先创建了一个哈夫曼堆,然后按照频率先将字符加入堆。接着通过递归构建哈夫曼并打印编码。最后计算WPL作为整个编码系统的压缩效率。
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值