572369写出哈夫曼树
时间: 2023-07-01 08:22:41 浏览: 85
很高兴回答你的问题!以下是一个示例哈夫曼树:
```
29
/ \
/ \
12 17
/ \ / \
6 6 8 9
/ \ / \
3 3 3 3
```
在上面的示例中,每个节点都是一个权重(或频率)和一个字符。哈夫曼树是一个二叉树,它的叶子节点代表字符,而每个非叶子节点代表权重。
哈夫曼树的构建过程可以是:
1. 统计每个字符在文本中出现的频率。
2. 将每个字符和它的频率作为一个节点插入到优先队列中。
3. 从队列中选择两个具有最小频率的节点,将它们合并成一个新的节点,并将合并后节点的频率设置为它们的和。
4. 将新节点插入到队列中。
5. 重复步骤3和4,直到队列中只剩下一个节点,这个节点就是哈夫曼树的根节点。
在上面的示例中,我们可以看到字符出现的频率和对应的节点。我们可以从下往上看,每次将两个最小的节点合并成一个新节点,最后得到了一个哈夫曼树。
相关问题
用C语言写出哈夫曼树的代码和注释
以下是用C语言实现哈夫曼树的代码和注释:
```c
#include <stdio.h>
#include <stdlib.h>
// 定义哈夫曼树节点结构体
typedef struct huffman_node {
int value; // 节点权值
struct huffman_node *left; // 左子节点指针
struct huffman_node *right; // 右子节点指针
} HuffmanNode;
// 定义优先队列(小根堆)结构体
typedef struct priority_queue {
HuffmanNode **nodes; // 节点数组指针
int size; // 当前队列大小
int capacity; // 队列容量
} PriorityQueue;
// 创建一个新的哈夫曼树节点
HuffmanNode *new_huffman_node(int value) {
HuffmanNode *node = (HuffmanNode *) malloc(sizeof(HuffmanNode));
node->value = value;
node->left = NULL;
node->right = NULL;
return node;
}
// 交换两个哈夫曼树节点的位置
void swap_nodes(HuffmanNode **a, HuffmanNode **b) {
HuffmanNode *tmp = *a;
*a = *b;
*b = tmp;
}
// 初始化优先队列
PriorityQueue *init_priority_queue(int capacity) {
PriorityQueue *queue = (PriorityQueue *) malloc(sizeof(PriorityQueue));
queue->nodes = (HuffmanNode **) malloc(sizeof(HuffmanNode *) * capacity);
queue->size = 0;
queue->capacity = capacity;
return queue;
}
// 向优先队列插入一个节点
void insert_node(PriorityQueue *queue, HuffmanNode *node) {
// 如果队列已满则返回
if (queue->size == queue->capacity) {
return;
}
// 将新节点插入队列末尾
queue->nodes[queue->size++] = node;
int index = queue->size - 1;
// 将新节点上浮到正确的位置
while (index > 0 && queue->nodes[index]->value < queue->nodes[(index - 1) / 2]->value) {
swap_nodes(&queue->nodes[index], &queue->nodes[(index - 1) / 2]);
index = (index - 1) / 2;
}
}
// 从优先队列中取出最小的节点
HuffmanNode *pop_min_node(PriorityQueue *queue) {
// 如果队列为空则返回 NULL
if (queue->size == 0) {
return NULL;
}
// 取出队列头部节点
HuffmanNode *min_node = queue->nodes[0];
// 将队列尾部节点移到头部
queue->nodes[0] = queue->nodes[--queue->size];
int index = 0;
// 将头部节点下沉到正确的位置
while (index * 2 + 1 < queue->size) {
int left_child_index = index * 2 + 1;
int right_child_index = index * 2 + 2;
int min_child_index = left_child_index;
if (right_child_index < queue->size && queue->nodes[right_child_index]->value < queue->nodes[left_child_index]->value) {
min_child_index = right_child_index;
}
if (queue->nodes[min_child_index]->value >= queue->nodes[index]->value) {
break;
}
swap_nodes(&queue->nodes[index], &queue->nodes[min_child_index]);
index = min_child_index;
}
return min_node;
}
// 构建哈夫曼树
HuffmanNode *build_huffman_tree(int *weights, int size) {
PriorityQueue *queue = init_priority_queue(size);
// 将所有树叶节点插入优先队列
for (int i = 0; i < size; i++) {
insert_node(queue, new_huffman_node(weights[i]));
}
// 不断取出两个最小的节点合并成一个新节点,直到队列中只有一个节点为止
while (queue->size > 1) {
HuffmanNode *left_child = pop_min_node(queue);
HuffmanNode *right_child = pop_min_node(queue);
HuffmanNode *new_node = new_huffman_node(left_child->value + right_child->value);
new_node->left = left_child;
new_node->right = right_child;
insert_node(queue, new_node);
}
HuffmanNode *root = pop_min_node(queue);
free(queue->nodes);
free(queue);
return root;
}
// 打印哈夫曼树的结构
void print_huffman_tree(HuffmanNode *root, int depth) {
if (root == NULL) {
return;
}
for (int i = 0; i < depth; i++) {
printf(" ");
}
if (root->left == NULL && root->right == NULL) {
printf("%d\n", root->value);
} else {
printf("+-\n");
print_huffman_tree(root->left, depth + 1);
print_huffman_tree(root->right, depth + 1);
}
}
int main() {
int weights[] = {3, 1, 4, 1, 5, 9, 2, 6, 5, 3};
int size = sizeof(weights) / sizeof(weights[0]);
HuffmanNode *root = build_huffman_tree(weights, size);
print_huffman_tree(root, 0);
return 0;
}
```
以上代码实现了哈夫曼树的构建和打印结构功能。可以通过修改 `weights` 数组中的元素来构建不同的哈夫曼树。
写出哈夫曼树和哈夫曼编码的实现只用stdio和iostream
下面是哈夫曼树和哈夫曼编码的实现示例,仅使用了stdio和iostream库:
```c++
#include <iostream>
#include <cstdio>
#include <queue>
#include <vector>
#include <cstring>
using namespace std;
const int MAXN = 10005;
int n;
int w[MAXN];
int parent[MAXN], lc[MAXN], rc[MAXN];
char code[MAXN][MAXN];
struct Node {
int id, w;
bool operator<(const Node& o) const {
return w > o.w;
}
};
void huffman() {
priority_queue<Node> q;
for (int i = 1; i <= n; ++i) {
q.push({i, w[i]});
}
int id = n + 1;
while (q.size() > 1) {
Node x = q.top();
q.pop();
Node y = q.top();
q.pop();
parent[x.id] = parent[y.id] = id;
lc[id] = x.id;
rc[id] = y.id;
w[id] = x.w + y.w;
q.push({id, w[id]});
++id;
}
}
void dfs(int u, char* cur) {
if (lc[u] == 0 && rc[u] == 0) {
strcpy(code[u], cur);
return;
}
int len = strlen(cur);
cur[len] = '0';
dfs(lc[u], cur);
cur[len] = '1';
dfs(rc[u], cur);
}
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; ++i) {
scanf("%d", &w[i]);
}
huffman();
dfs(n * 2 - 1, code[n * 2 - 1]);
for (int i = 1; i <= n; ++i) {
printf("char %c : %s\n", 'A' + i - 1, code[i]);
}
return 0;
}
```
上述代码实现了哈夫曼树和哈夫曼编码的构建,其中用到了优先队列和深度优先遍历。在输入时,需要先输入字符集的大小n,然后依次输入每个字符的权值。输出时,对于每个字符,输出它的字符编码。
阅读全文