c语言编写一个哈夫曼码的编码系统,一个完整的系统应具有以下功能:选择菜单1 1)初始化。从终端读入字符集大小n,以及n个字符和n个权值,建立哈夫曼树。 2)编码。利用已建好的哈夫曼树,对字符进行编码,并输出各个字符对应的编码序列。若输入的字符不存在,则提示不能进行字符编码。 3)译码。输入一串01代码,对编码序列进行译码,并输出对应的字符序列;若没有对应的字符序列,则显示编码有误。 4)哈夫曼树:输出对应的哈夫曼树;
时间: 2023-07-16 18:14:12 浏览: 490
哈夫曼编码c语言版下载
4星 · 用户满意度95%
以下是一个简单的C语言实现:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 定义哈夫曼树节点结构体
typedef struct huffman_node {
char ch; // 字符
int weight; // 权值
struct huffman_node *left, *right; // 左右子节点
} huffman_node;
// 定义哈夫曼编码节点结构体
typedef struct huffman_code {
char ch; // 字符
char *code; // 编码
} huffman_code;
// 创建哈夫曼树
huffman_node* create_huffman_tree(char *chars, int *weights, int n) {
// 创建节点数组
huffman_node **nodes = (huffman_node**)malloc(n * sizeof(huffman_node*));
for (int i = 0; i < n; i++) {
nodes[i] = (huffman_node*)malloc(sizeof(huffman_node));
nodes[i]->ch = chars[i];
nodes[i]->weight = weights[i];
nodes[i]->left = nodes[i]->right = NULL;
}
while (n > 1) {
// 找出权值最小的两个节点
int min1 = 0, min2 = 1;
if (nodes[min1]->weight > nodes[min2]->weight) {
min1 = 1;
min2 = 0;
}
for (int i = 2; i < n; i++) {
if (nodes[i]->weight < nodes[min1]->weight) {
min2 = min1;
min1 = i;
} else if (nodes[i]->weight < nodes[min2]->weight) {
min2 = i;
}
}
// 创建新节点
huffman_node *new_node = (huffman_node*)malloc(sizeof(huffman_node));
new_node->weight = nodes[min1]->weight + nodes[min2]->weight;
new_node->left = nodes[min1];
new_node->right = nodes[min2];
// 删除已合并的两个节点
if (min1 < min2) {
nodes[min1] = new_node;
nodes[min2] = nodes[n-1];
} else {
nodes[min2] = new_node;
nodes[min1] = nodes[n-1];
}
n--;
}
huffman_node *root = nodes[0];
free(nodes);
return root;
}
// 递归获取哈夫曼编码
void get_huffman_code(huffman_node *node, char *code, int len, huffman_code *codes) {
if (node->left == NULL && node->right == NULL) {
// 叶子节点,保存编码
for (int i = 0; i < len; i++) {
codes[node->ch].code[i] = code[i];
}
codes[node->ch].code[len] = '\0';
return;
}
code[len] = '0';
get_huffman_code(node->left, code, len+1, codes);
code[len] = '1';
get_huffman_code(node->right, code, len+1, codes);
}
// 初始化哈夫曼编码
void init_huffman_codes(huffman_node *root, huffman_code *codes) {
char code[256];
memset(code, 0, sizeof(code));
get_huffman_code(root, code, 0, codes);
}
// 编码单个字符
char* encode_character(char ch, huffman_code *codes) {
if (codes[ch].code[0] == '\0') {
printf("不能进行字符编码: %c\n", ch);
return NULL;
}
return strdup(codes[ch].code);
}
// 编码字符串
char* encode_string(char *str, huffman_code *codes) {
int len = strlen(str);
char *result = (char*)malloc(1000 * sizeof(char));
result[0] = '\0';
for (int i = 0; i < len; i++) {
char *code = encode_character(str[i], codes);
if (code == NULL) {
free(result);
return NULL;
}
strcat(result, code);
free(code);
}
return result;
}
// 译码单个字符
char decode_character(char *code, huffman_node *root) {
huffman_node *node = root;
while (*code != '\0') {
if (*code == '0') {
node = node->left;
} else {
node = node->right;
}
code++;
}
return node->ch;
}
// 译码字符串
char* decode_string(char *code, huffman_node *root) {
int len = strlen(code);
char *result = (char*)malloc((len+1) * sizeof(char));
int pos = 0;
while (*code != '\0') {
char ch = decode_character(code, root);
if (ch == '\0') {
printf("编码有误: %s\n", code);
free(result);
return NULL;
}
result[pos++] = ch;
code += strlen(root[ch].code);
}
result[pos] = '\0';
return result;
}
// 输出哈夫曼树
void print_huffman_tree(huffman_node *root, int depth) {
if (root == NULL) {
return;
}
for (int i = 0; i < depth; i++) {
printf(" ");
}
if (root->left == NULL && root->right == NULL) {
printf("%c\n", root->ch);
} else {
printf("*\n");
print_huffman_tree(root->left, depth+1);
print_huffman_tree(root->right, depth+1);
}
}
int main() {
int n;
printf("请输入字符集大小n: ");
scanf("%d", &n);
char *chars = (char*)malloc(n * sizeof(char));
int *weights = (int*)malloc(n * sizeof(int));
for (int i = 0; i < n; i++) {
printf("请输入第%d个字符和权值: ", i+1);
scanf(" %c %d", &chars[i], &weights[i]);
}
// 创建哈夫曼树
huffman_node *root = create_huffman_tree(chars, weights, n);
// 初始化哈夫曼编码
huffman_code *codes = (huffman_code*)malloc(256 * sizeof(huffman_code));
for (int i = 0; i < 256; i++) {
codes[i].ch = i;
codes[i].code = (char*)calloc(256, sizeof(char));
}
init_huffman_codes(root, codes);
while (1) {
int choice;
printf("请选择操作:\n");
printf("1. 初始化\n");
printf("2. 编码\n");
printf("3. 译码\n");
printf("4. 哈夫曼树\n");
printf("5. 退出\n");
printf("选择:");
scanf("%d", &choice);
switch (choice) {
case 1: {
printf("请输入字符集大小n: ");
scanf("%d", &n);
chars = (char*)realloc(chars, n * sizeof(char));
weights = (int*)realloc(weights, n * sizeof(int));
for (int i = 0; i < n; i++) {
printf("请输入第%d个字符和权值: ", i+1);
scanf(" %c %d", &chars[i], &weights[i]);
}
// 重新创建哈夫曼树
root = create_huffman_tree(chars, weights, n);
// 重新初始化哈夫曼编码
for (int i = 0; i < 256; i++) {
free(codes[i].code);
codes[i].code = (char*)calloc(256, sizeof(char));
}
init_huffman_codes(root, codes);
break;
}
case 2: {
char str[100];
printf("请输入字符串: ");
scanf("%s", str);
char *code = encode_string(str, codes);
if (code != NULL) {
printf("编码结果: %s\n", code);
free(code);
}
break;
}
case 3: {
char code[1000];
printf("请输入编码: ");
scanf("%s", code);
char *str = decode_string(code, root);
if (str != NULL) {
printf("译码结果: %s\n", str);
free(str);
}
break;
}
case 4: {
print_huffman_tree(root, 0);
break;
}
case 5: {
// 释放内存
for (int i = 0; i < 256; i++) {
free(codes[i].code);
}
free(codes);
free(chars);
free(weights);
return 0;
}
default: {
printf("无效的选择,请重新选择。\n");
break;
}
}
}
}
```
运行程序后,可以进行初始化、编码、译码、输出哈夫曼树等操作。例如:
```
请输入字符集大小n: 5
请输入第1个字符和权值: A 5
请输入第2个字符和权值: B 2
请输入第3个字符和权值: C 10
请输入第4个字符和权值: D 3
请输入第5个字符和权值: E 6
请选择操作:
1. 初始化
2. 编码
3. 译码
4. 哈夫曼树
5. 退出
选择:4
*
A
*
B
*
D
E
C
请选择操作:
1. 初始化
2. 编码
3. 译码
4. 哈夫曼树
5. 退出
选择:2
请输入字符串: ABCDE
编码结果: 000100110111010
请选择操作:
1. 初始化
2. 编码
3. 译码
4. 哈夫曼树
5. 退出
选择:3
请输入编码: 000100110111010
译码结果: ABCDE
```
阅读全文