C语言哈夫曼树与哈夫曼编码
时间: 2023-11-06 16:49:31 浏览: 149
哈夫曼树(Huffman tree)是一种用于数据压缩的树形结构,它是由字符出现频率构建而成的最优二叉树。哈夫曼编码(Huffman coding)是一种变长编码方式,通过将出现频率高的字符使用较短的编码,而出现频率低的字符使用较长的编码,从而实现数据压缩。
在C语言中实现哈夫曼树和哈夫曼编码,可以按照以下步骤进行:
1. 统计字符的出现频率:遍历待压缩的数据,统计每个字符的出现频率。
2. 构建哈夫曼树:根据字符的出现频率构建哈夫曼树。可以使用最小堆(min heap)来辅助构建过程。首先将每个字符作为一个叶子节点插入到最小堆中,然后反复从堆中选取频率最小的两个节点,合并为一个新节点,并将新节点插入回堆中,直到堆中只剩下一个节点,即为根节点,构成了哈夫曼树。
3. 生成哈夫曼编码:从根节点开始遍历哈夫曼树,记录路径上经过的左右分支,将左分支记为0,右分支记为1。叶子节点上的路径即为对应字符的哈夫曼编码。
4. 进行数据压缩:遍历待压缩的数据,将每个字符替换为对应的哈夫曼编码,将编码后的结果进行存储或传输。
5. 进行数据解压:使用相同的哈夫曼树和哈夫曼编码表,将编码后的数据逐个进行解码,还原出原始数据。
以上是大致的实现过程,具体的代码实现可以根据自己的需求和编程能力进行设计。希望对你有所帮助!
相关问题
C语言哈夫曼树编码输出
下面是一个简单的C语言程序,实现哈夫曼树的编码输出功能:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_NODE_NUM 100 // 哈夫曼树最大节点数
// 定义哈夫曼树节点结构体
typedef struct HuffmanNode {
char ch; // 字符
float weight; // 权值
int parent; // 父节点
int left; // 左子节点
int right; // 右子节点
char code[MAX_NODE_NUM]; // 编码
} HuffmanNode;
// 初始化哈夫曼树
void initHuffmanTree(HuffmanNode *huffTree, int n) {
int i;
for (i = 0; i < n; i++) {
huffTree[i].parent = -1;
huffTree[i].left = -1;
huffTree[i].right = -1;
memset(huffTree[i].code, 0, sizeof(huffTree[i].code));
}
}
// 选择权值最小的两个节点
void selectMin(HuffmanNode *huffTree, int n, int *p1, int *p2) {
int i;
float min1 = 1e9, min2 = 1e9;
for (i = 0; i < n; i++) {
if (huffTree[i].weight < min1 && huffTree[i].parent == -1) {
min2 = min1;
min1 = huffTree[i].weight;
*p2 = *p1;
*p1 = i;
} else if (huffTree[i].weight < min2 && huffTree[i].parent == -1) {
min2 = huffTree[i].weight;
*p2 = i;
}
}
}
// 构建哈夫曼树
void createHuffmanTree(HuffmanNode *huffTree, float *weights, int n) {
int i, p1, p2;
initHuffmanTree(huffTree, n);
for (i = 0; i < n; i++) {
huffTree[i].weight = weights[i];
huffTree[i].ch = 'A' + i;
}
for (i = 0; i < n - 1; i++) {
selectMin(huffTree, n + i, &p1, &p2);
huffTree[p1].parent = n + i;
huffTree[p2].parent = n + i;
huffTree[n + i].weight = huffTree[p1].weight + huffTree[p2].weight;
huffTree[n + i].left = p1;
huffTree[n + i].right = p2;
}
}
// 编码
void encode(HuffmanNode *huffTree, int n) {
int i, j, parent, current;
for (i = 0; i < n; i++) {
parent = huffTree[i].parent;
current = i;
while (parent != -1) {
if (huffTree[parent].left == current) {
strcat(huffTree[i].code, "0");
} else {
strcat(huffTree[i].code, "1");
}
current = parent;
parent = huffTree[current].parent;
}
strrev(huffTree[i].code); // 将编码反转
}
}
// 输出哈夫曼树编码
void printHuffmanCode(HuffmanNode *huffTree, int n) {
int i;
for (i = 0; i < n; i++) {
printf("%c: %s\n", huffTree[i].ch, huffTree[i].code);
}
}
int main() {
float weights[] = {0.15, 0.1, 0.2, 0.3, 0.25};
int n = sizeof(weights) / sizeof(weights[0]);
HuffmanNode huffTree[MAX_NODE_NUM];
createHuffmanTree(huffTree, weights, n);
encode(huffTree, n);
printHuffmanCode(huffTree, n);
return 0;
}
```
这个程序实现了一个简单的哈夫曼树编码输出功能,可以参考它来理解哈夫曼树编码的实现过程。
c语言哈夫曼树编码译码
哈夫曼编码是一种基于二叉树的编码方式,可以实现无损压缩数据的功能。下面是C语言实现哈夫曼树编码和译码的示例代码:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 哈夫曼树的节点结构体
typedef struct huffman_node {
char data; // 数据
int freq; // 频率
struct huffman_node *left; // 左子节点
struct huffman_node *right; // 右子节点
} huffman_node_t;
// 哈夫曼编码表的结构体
typedef struct huffman_table {
char data; // 数据
char code[256]; // 编码
} huffman_table_t;
// 构建哈夫曼树
huffman_node_t* build_huffman_tree(char* data, int* freq, int n) {
huffman_node_t **nodes = (huffman_node_t**)malloc(n * sizeof(huffman_node_t*));
for (int i = 0; i < n; i++) {
huffman_node_t *node = (huffman_node_t*)malloc(sizeof(huffman_node_t));
node->data = data[i];
node->freq = freq[i];
node->left = NULL;
node->right = NULL;
nodes[i] = node;
}
while (n > 1) {
// 找出频率最小的两个节点
int min1 = 0, min2 = 1;
if (nodes[0]->freq > nodes[1]->freq) {
min1 = 1;
min2 = 0;
}
for (int i = 2; i < n; i++) {
if (nodes[i]->freq < nodes[min1]->freq) {
min2 = min1;
min1 = i;
} else if (nodes[i]->freq < nodes[min2]->freq) {
min2 = i;
}
}
// 合并频率最小的两个节点
huffman_node_t *parent = (huffman_node_t*)malloc(sizeof(huffman_node_t));
parent->data = 0;
parent->freq = nodes[min1]->freq + nodes[min2]->freq;
parent->left = nodes[min1];
parent->right = nodes[min2];
if (min1 < min2) {
nodes[min1] = parent;
nodes[min2] = nodes[n - 1];
} else {
nodes[min2] = parent;
nodes[min1] = nodes[n - 1];
}
n--;
}
return nodes[0];
}
// 生成哈夫曼编码表
void generate_huffman_table(huffman_node_t *root, char* code, int depth, huffman_table_t* table) {
if (root->left == NULL && root->right == NULL) {
table[root->data].data = root->data;
strcpy(table[root->data].code, code);
return;
}
code[depth] = '0';
generate_huffman_table(root->left, code, depth + 1, table);
code[depth] = '1';
generate_huffman_table(root->right, code, depth + 1, table);
}
// 哈夫曼编码
char* huffman_encode(char* data, huffman_table_t* table) {
int n = strlen(data);
char* code = (char*)malloc(n * 256 * sizeof(char));
int k = 0;
for (int i = 0; i < n; i++) {
strcat(code, table[data[i]].code);
}
return code;
}
// 哈夫曼解码
char* huffman_decode(char* code, huffman_node_t* root) {
int n = strlen(code);
char* data = (char*)malloc(n * sizeof(char));
huffman_node_t* p = root;
int k = 0;
for (int i = 0; i < n; i++) {
if (code[i] == '0') {
p = p->left;
} else {
p = p->right;
}
if (p->left == NULL && p->right == NULL) {
data[k++] = p->data;
p = root;
}
}
return data;
}
int main() {
char data[] = "ABCDAAAABBBCDEFG";
int freq[] = {3, 4, 3, 2, 2, 2, 1, 2, 1, 1};
int n = strlen(data);
// 构建哈夫曼树
huffman_node_t* root = build_huffman_tree(data, freq, n);
// 生成哈夫曼编码表
char code[256];
memset(code, 0, sizeof(code));
huffman_table_t table[256];
generate_huffman_table(root, code, 0, table);
// 哈夫曼编码
char* encoded = huffman_encode(data, table);
// 哈夫曼解码
char* decoded = huffman_decode(encoded, root);
printf("原始数据:%s\n", data);
printf("哈夫曼编码:%s\n", encoded);
printf("哈夫曼解码:%s\n", decoded);
return 0;
}
```
以上代码实现了哈夫曼树的构建、哈夫曼编码表的生成、哈夫曼编码和哈夫曼解码的功能。在实际应用中,需要根据具体的需求对代码进行修改和优化。
阅读全文