用c语言写一个代码,输入一串字符串,根据给定的字符串中字符出现的频率建立相应的哈夫曼树,构造哈夫曼编码表,在此基础上可以对压缩文件进行压缩,同时可以对压缩后的二进制编码文件进行解压

时间: 2024-03-21 07:44:28 浏览: 19
好的,以下是一个基于C语言的实现,实现了输入字符串后建立哈夫曼树,并构造哈夫曼编码表的功能。同时也提供了对压缩文件进行压缩和解压缩的功能。注意,以下代码仅供参考,实际使用时可能需要根据具体场景进行修改和完善。 ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdbool.h> #include <stdint.h> #define MAX_LEN 256 typedef struct HuffmanNode { char val; int freq; struct HuffmanNode* left; struct HuffmanNode* right; } HuffmanNode; typedef struct CodeTable { char ch; char* code; } CodeTable; CodeTable code_table[MAX_LEN]; int code_table_size = 0; void print_code_table() { printf("Huffman code table:\n"); for (int i = 0; i < code_table_size; i++) { printf("%c: %s\n", code_table[i].ch, code_table[i].code); } } void free_huffman_tree(HuffmanNode* root) { if (root) { free_huffman_tree(root->left); free_huffman_tree(root->right); free(root); } } int cmp_node(const void* a, const void* b) { HuffmanNode* node1 = *(HuffmanNode**)a; HuffmanNode* node2 = *(HuffmanNode**)b; return node1->freq - node2->freq; } void build_huffman_tree(char* s, int n, HuffmanNode** root) { int freq[MAX_LEN] = {0}; for (int i = 0; i < n; i++) { freq[s[i]]++; } HuffmanNode* nodes[MAX_LEN]; int nodes_size = 0; for (int i = 0; i < MAX_LEN; i++) { if (freq[i] > 0) { nodes[nodes_size] = (HuffmanNode*)malloc(sizeof(HuffmanNode)); nodes[nodes_size]->val = i; nodes[nodes_size]->freq = freq[i]; nodes[nodes_size]->left = NULL; nodes[nodes_size]->right = NULL; nodes_size++; } } while (nodes_size > 1) { qsort(nodes, nodes_size, sizeof(HuffmanNode*), cmp_node); HuffmanNode* node1 = nodes[0]; HuffmanNode* node2 = nodes[1]; HuffmanNode* merged_node = (HuffmanNode*)malloc(sizeof(HuffmanNode)); merged_node->val = -1; merged_node->freq = node1->freq + node2->freq; merged_node->left = node1; merged_node->right = node2; nodes[0] = merged_node; nodes_size--; for (int i = 1; i < nodes_size; i++) { nodes[i] = nodes[i + 1]; } } *root = nodes[0]; } void dfs_huffman_tree(HuffmanNode* root, char* code, int len) { if (root->val != -1) { CodeTable ct = {root->val, (char*)malloc((len + 1) * sizeof(char))}; strcpy(ct.code, code); code_table[code_table_size] = ct; code_table_size++; } if (root->left) { code[len] = '0'; dfs_huffman_tree(root->left, code, len + 1); } if (root->right) { code[len] = '1'; dfs_huffman_tree(root->right, code, len + 1); } } void build_huffman_code_table(HuffmanNode* root) { char code[MAX_LEN] = {0}; dfs_huffman_tree(root, code, 0); } int get_bit(uint8_t byte, int i) { return (byte >> (7 - i)) & 1; } void compress_file(char* src_file, char* dst_file) { FILE* fp_src = fopen(src_file, "rb"); if (!fp_src) { printf("Error: cannot open source file!\n"); return; } FILE* fp_dst = fopen(dst_file, "wb"); if (!fp_dst) { printf("Error: cannot open destination file!\n"); fclose(fp_src); return; } // Count frequency int freq[MAX_LEN] = {0}; char ch; while (fread(&ch, sizeof(char), 1, fp_src) == 1) { freq[ch]++; } rewind(fp_src); // Build Huffman tree HuffmanNode* root = NULL; build_huffman_tree(NULL, MAX_LEN, &root); free_huffman_tree(root); build_huffman_tree(NULL, MAX_LEN, &root); // Build Huffman code table code_table_size = 0; build_huffman_code_table(root); // Write Huffman code table to file fwrite(&code_table_size, sizeof(int), 1, fp_dst); for (int i = 0; i < code_table_size; i++) { fwrite(&code_table[i].ch, sizeof(char), 1, fp_dst); int code_len = strlen(code_table[i].code); fwrite(&code_len, sizeof(int), 1, fp_dst); fwrite(code_table[i].code, sizeof(char), code_len, fp_dst); } // Compress data and write to file uint8_t byte = 0; int bit_count = 0; while (fread(&ch, sizeof(char), 1, fp_src) == 1) { char* code = NULL; for (int i = 0; i < code_table_size; i++) { if (code_table[i].ch == ch) { code = code_table[i].code; break; } } int code_len = strlen(code); for (int i = 0; i < code_len; i++) { byte |= (code[i] - '0') << (7 - bit_count); bit_count++; if (bit_count == 8) { fwrite(&byte, sizeof(uint8_t), 1, fp_dst); byte = 0; bit_count = 0; } } } if (bit_count > 0) { fwrite(&byte, sizeof(uint8_t), 1, fp_dst); } fclose(fp_src); fclose(fp_dst); } void decompress_file(char* src_file, char* dst_file) { FILE* fp_src = fopen(src_file, "rb"); if (!fp_src) { printf("Error: cannot open source file!\n"); return; } FILE* fp_dst = fopen(dst_file, "wb"); if (!fp_dst) { printf("Error: cannot open destination file!\n"); fclose(fp_src); return; } // Read Huffman code table from file fread(&code_table_size, sizeof(int), 1, fp_src); for (int i = 0; i < code_table_size; i++) { fread(&code_table[i].ch, sizeof(char), 1, fp_src); int code_len; fread(&code_len, sizeof(int), 1, fp_src); code_table[i].code = (char*)malloc((code_len + 1) * sizeof(char)); fread(code_table[i].code, sizeof(char), code_len, fp_src); code_table[i].code[code_len] = '\0'; } // Build Huffman tree HuffmanNode* root = NULL; build_huffman_tree(NULL, MAX_LEN, &root); free_huffman_tree(root); build_huffman_tree(NULL, MAX_LEN, &root); // Decompress data and write to file HuffmanNode* current = root; uint8_t byte; while (fread(&byte, sizeof(uint8_t), 1, fp_src) == 1) { for (int i = 0; i < 8; i++) { int bit = get_bit(byte, i); if (bit == 0) { current = current->left; } else { current = current->right; } if (current->val != -1) { fwrite(&current->val, sizeof(char), 1, fp_dst); current = root; } } } fclose(fp_src); fclose(fp_dst); } int main() { char s[MAX_LEN]; printf("Please input a string:\n"); fgets(s, MAX_LEN, stdin); int n = strlen(s); if (s[n - 1] == '\n') { s[n - 1] = '\0'; n--; } // Build Huffman tree HuffmanNode* root = NULL; build_huffman_tree(s, n, &root); // Build Huffman code table code_table_size = 0; build_huffman_code_table(root); print_code_table(); // Compress data and write to file compress_file("input.txt", "output.bin"); // Decompress data and write to file decompress_file("output.bin", "output.txt"); free_huffman_tree(root); return 0; } ```

相关推荐

描述 输入一串字符串,根据给定的字符串中字符出现的频率建立相应哈夫曼树,构造哈夫曼编码表,在此基础上可以对待压缩文件进行压缩(即编码),同时可以对压缩后的二进制编码文件进行解压(即译码)。 输入 多组数据,每组数据一行,为一个字符串(只考虑26个小写字母即可)。当输入字符串为“0”时,输入结束。 输出 每组数据输出2n+3行(n为输入串中字符类别的个数)。第一行为统计出来的字符出现频率(只输出存在的字符,格式为:字符:频度),每两组字符之间用一个空格分隔,字符按照ASCII码从小到大的顺序排列。第二行至第2n行为哈夫曼树的存储结构的终态(形如教材139页表5.2(b),一行当中的数据用空格分隔)。第2n+1行为每个字符的哈夫曼编码(只输出存在的字符,格式为:字符:编码),每两组字符之间用一个空格分隔,字符按照ASCII码从小到大的顺序排列。第2n+2行为编码后的字符串,第2n+3行为解码后的字符串(与输入的字符串相同)。 样例输入1 aaaaaaabbbbbccdddd aabccc 0 样例输出1 a:7 b:5 c:2 d:4 1 7 7 0 0 2 5 6 0 0 3 2 5 0 0 4 4 5 0 0 5 6 6 3 4 6 11 7 2 5 7 18 0 1 6 a:0 b:10 c:110 d:111 00000001010101010110110111111111111 aaaaaaabbbbbccdddd a:2 b:1 c:3 1 2 4 0 0 2 1 4 0 0 3 3 5 0 0 4 3 5 2 1 5 6 0 3 4 a:11 b:10 c:0 111110000 aabccc使用c语言写出完整的代码并加上注释,分析时间复杂度和空间复杂读

最新推荐

recommend-type

基于三层感知机实现手写数字识别-内含源码和说明书.zip

基于三层感知机实现手写数字识别-内含源码和说明书.zip
recommend-type

setuptools-40.7.0.zip

Python库是一组预先编写的代码模块,旨在帮助开发者实现特定的编程任务,无需从零开始编写代码。这些库可以包括各种功能,如数学运算、文件操作、数据分析和网络编程等。Python社区提供了大量的第三方库,如NumPy、Pandas和Requests,极大地丰富了Python的应用领域,从数据科学到Web开发。Python库的丰富性是Python成为最受欢迎的编程语言之一的关键原因之一。这些库不仅为初学者提供了快速入门的途径,而且为经验丰富的开发者提供了强大的工具,以高效率、高质量地完成复杂任务。例如,Matplotlib和Seaborn库在数据可视化领域内非常受欢迎,它们提供了广泛的工具和技术,可以创建高度定制化的图表和图形,帮助数据科学家和分析师在数据探索和结果展示中更有效地传达信息。
recommend-type

搭建VGG16神经网络实现图像分类-内含源码和说明书.zip

搭建VGG16神经网络实现图像分类-内含源码和说明书.zip
recommend-type

setuptools-40.6.1.zip

Python库是一组预先编写的代码模块,旨在帮助开发者实现特定的编程任务,无需从零开始编写代码。这些库可以包括各种功能,如数学运算、文件操作、数据分析和网络编程等。Python社区提供了大量的第三方库,如NumPy、Pandas和Requests,极大地丰富了Python的应用领域,从数据科学到Web开发。Python库的丰富性是Python成为最受欢迎的编程语言之一的关键原因之一。这些库不仅为初学者提供了快速入门的途径,而且为经验丰富的开发者提供了强大的工具,以高效率、高质量地完成复杂任务。例如,Matplotlib和Seaborn库在数据可视化领域内非常受欢迎,它们提供了广泛的工具和技术,可以创建高度定制化的图表和图形,帮助数据科学家和分析师在数据探索和结果展示中更有效地传达信息。
recommend-type

华为OD机试D卷 - 判断字符串子序列 - 免费看解析和代码.html

私信博主免费获取真题解析以及代码
recommend-type

zigbee-cluster-library-specification

最新的zigbee-cluster-library-specification说明文档。
recommend-type

管理建模和仿真的文件

管理Boualem Benatallah引用此版本:布阿利姆·贝纳塔拉。管理建模和仿真。约瑟夫-傅立叶大学-格勒诺布尔第一大学,1996年。法语。NNT:电话:00345357HAL ID:电话:00345357https://theses.hal.science/tel-003453572008年12月9日提交HAL是一个多学科的开放存取档案馆,用于存放和传播科学研究论文,无论它们是否被公开。论文可以来自法国或国外的教学和研究机构,也可以来自公共或私人研究中心。L’archive ouverte pluridisciplinaire
recommend-type

实现实时数据湖架构:Kafka与Hive集成

![实现实时数据湖架构:Kafka与Hive集成](https://img-blog.csdnimg.cn/img_convert/10eb2e6972b3b6086286fc64c0b3ee41.jpeg) # 1. 实时数据湖架构概述** 实时数据湖是一种现代数据管理架构,它允许企业以低延迟的方式收集、存储和处理大量数据。与传统数据仓库不同,实时数据湖不依赖于预先定义的模式,而是采用灵活的架构,可以处理各种数据类型和格式。这种架构为企业提供了以下优势: - **实时洞察:**实时数据湖允许企业访问最新的数据,从而做出更明智的决策。 - **数据民主化:**实时数据湖使各种利益相关者都可
recommend-type

用 Python 画一个可以动的爱心

好的,我可以帮助您使用Python来绘制一个动态的爱心。您可以使用turtle库来实现。以下是实现代码: ```python import turtle import math # 设置画布和画笔 canvas = turtle.Screen() canvas.bgcolor("black") pencil = turtle.Turtle() pencil.speed(0) pencil.color("red", "pink") pencil.pensize(3) # 定义爱心函数 def draw_love(heart_size, x_offset=0, y_offset=0):
recommend-type

JSBSim Reference Manual

JSBSim参考手册,其中包含JSBSim简介,JSBSim配置文件xml的编写语法,编程手册以及一些应用实例等。其中有部分内容还没有写完,估计有生之年很难看到完整版了,但是内容还是很有参考价值的。