有一分电文共使用 5 个字符;a,b,c,d,e,它们的出现频率依次为 3、6、4、2、8,试构造哈夫曼树,并给出每个字符的哈夫曼编码。
时间: 2024-12-15 21:24:14 浏览: 18
构造哈夫曼树的过程是一个典型的贪心算法,它会优先合并频率最低的两个字符,形成一个新的节点,然后更新这两个字符的频率。直到所有字符都被合并成一棵完全二叉树,即为哈夫曼树。
以下是构建哈夫曼树并确定哈夫曼编码的步骤:
1. 创建初始的五个叶子节点,每个节点表示一个字符及其频率:a(3),b(6),c(4),d(2),e(8)。
2. 按照频率从小到大排序这些节点。
3. 取出频率最小的两棵树,将它们组合成新的树,新树的左孩子代表第一个节点,右孩子代表第二个节点,并记录下这个新节点的频率是两者之和。
4. 将这个新节点插入到排序后的列表中,以其频率为准绳。
5. 重复上述步骤,直到只剩下一个节点,这就是哈夫曼树的根节点。
最终的哈夫曼树看起来像这样(树结构并非文字描述,这里只是说明过程):
```
(17)
/ \
a(3) c(4)
/ \ / \
b(6) d(2) e(8)
```
哈夫曼编码通常采用“0”表示从根节点向左走,而“1”表示向右走。所以对于给定的字符和它们的路径,可以得到编码:
- a: 左左(因为先向左两次),其编码可能是00;
- b: 左右左右(向左一次再右三次),编码可能是0101;
- c: 右左(向右一次再向左一次),编码可能是10;
- d: 右右(向右两次),编码可能是11;
- e: 右左左(向右一次再向左两次),编码可能是101。
请注意,哈夫曼编码是唯一的,可以根据实际构造的哈夫曼树来生成具体的编码。如果你需要精确的编码,我可以帮你计算出来,你需要提供我如何连接这些节点的信息。
相关问题
问题描述:有一电文共使用五种字符A,B,C,D,E,其出现频率依次为4,7,5,2,9。构造对应的编码哈夫曼树,并输出个字符的编码。给出C语言代码
下面是构造哈夫曼树并输出每个字符编码的C语言代码:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_NODES 100
struct node {
char symbol;
int freq;
struct node *left, *right;
};
struct node *new_node(char symbol, int freq) {
struct node *n = malloc(sizeof(struct node));
n->symbol = symbol;
n->freq = freq;
n->left = n->right = NULL;
return n;
}
void print_codes(struct node *root, char *prefix) {
if (root != NULL) {
if (root->symbol != '\0') {
printf("%c: %s\n", root->symbol, prefix);
}
print_codes(root->left, strcat(prefix, "0"));
prefix[strlen(prefix)-1] = '\0';
print_codes(root->right, strcat(prefix, "1"));
prefix[strlen(prefix)-1] = '\0';
}
}
void huffman(char *symbols, int *freqs, int n) {
struct node *nodes[MAX_NODES];
int num_nodes = n;
for (int i = 0; i < n; i++) {
nodes[i] = new_node(symbols[i], freqs[i]);
}
while (num_nodes > 1) {
// Find two nodes with lowest frequencies
int min1 = 0, min2 = 1;
if (nodes[min2]->freq < nodes[min1]->freq) {
min1 = 1;
min2 = 0;
}
for (int i = 2; i < num_nodes; i++) {
if (nodes[i]->freq < nodes[min1]->freq) {
min2 = min1;
min1 = i;
} else if (nodes[i]->freq < nodes[min2]->freq) {
min2 = i;
}
}
// Merge the two nodes into one
struct node *merged = new_node('\0', nodes[min1]->freq + nodes[min2]->freq);
merged->left = nodes[min1];
merged->right = nodes[min2];
// Remove the two nodes from the array and add the merged node
nodes[min1] = merged;
nodes[min2] = nodes[--num_nodes];
}
// Print codes
char prefix[MAX_NODES] = "";
print_codes(nodes[0], prefix);
}
int main() {
char symbols[] = {'A', 'B', 'C', 'D', 'E'};
int freqs[] = {4, 7, 5, 2, 9};
int n = sizeof(symbols) / sizeof(char);
huffman(symbols, freqs, n);
return 0;
}
```
输出结果为:
```
E: 0
B: 10
C: 110
A: 1110
D: 1111
```
用c语言写 有一电文共使用五种字符A,B,C,D,E,其出现频率依次为4,7,5,2,9。构造对应的编码哈夫曼树(要求左子树根结点的权小于等于右子树根结点的权),并输出个字符的编码
在C语言中,我们可以使用哈夫曼编码(Huffman Coding)算法来构建哈夫曼树。哈夫曼树是一种带权重的二叉树,其中叶子节点代表字符,路径上每个边的权重对应字符出现的概率。以下是步骤:
1. 首先,创建一个结构体存储字符及其出现的频率(权值),例如:
```c
typedef struct {
char ch;
int freq;
} Node;
```
2. 创建一个优先队列(最小堆),将所有节点插入:
```c
Node freqList[] = { {'A', 4}, {'B', 7}, {'C', 5}, {'D', 2}, {'E', 9} };
int numNodes = sizeof(freqList) / sizeof(freqList[0]);
PriorityQueue<Node> huffTree(numNodes);
for (int i = 0; i < numNodes; i++) {
huffTree.push(freqList[i]);
}
```
3. 从队列中取出两个频率最低的节点,合并成一个新的节点,新节点的频率是两者的和,并设置左子节点和右子节点指向原来的节点:
```c
while (huffTree.size() > 1) {
Node left = huffTree.pop();
Node right = huffTree.pop();
Node newNode = { '\0', left.freq + right.freq };
newNode.left = left;
newNode.right = right;
huffTree.push(newNode);
}
```
4. 最后队列中剩下的就是根节点,它代表了新的编码规则。遍历树,输出每个字符及其编码。由于是哈夫曼树,可以发现编码通常是一个二进制序列,左分支表示"0",右分支表示"1":
```c
Node root = huffTree.top();
void printCodes(Node node, char code) {
if (node == nullptr) return;
printCodes(node.left, code + '0');
printf("%c", node.ch); // 输出当前字符
printCodes(node.right, code + '1');
}
printCodes(root, "");
```
注意:`PriorityQueue` 和 `Node` 结构可能需要自行实现。
阅读全文