给定一段ascii文本或一个ascii文本文件,统计其中每个字符出现的频率,并使用哈夫曼
时间: 2023-12-22 21:00:45 浏览: 181
哈夫曼编码是一种基于字符频率的压缩算法,它通过对出现频率较高的字符分配较短的编码,从而实现对文本的高效压缩。在实现哈夫曼编码之前,首先需要统计给定ASCII文本中每个字符的出现频率。
首先,我们可以编写一个程序来读取ASCII文本文件,并统计其中每个字符的出现频率。我们可以使用一个哈希表或者数组来记录每个字符出现的次数。然后,我们可以使用这些频率数据来构建哈夫曼树。
哈夫曼树是一种特殊的二叉树,它的叶子节点对应着文本中的字符,而每个字符的出现频率则对应着叶子节点的权重。我们可以通过构建哈夫曼树来得到每个字符对应的哈夫曼编码。
接下来,我们可以使用哈夫曼树来生成每个字符对应的哈夫曼编码。通过从根节点出发,沿着树向下遍历到达每个字符的叶子节点,记录下经过的路径(0表示向左,1表示向右),即可得到每个字符的哈夫曼编码。
最后,我们将这些字符和对应的哈夫曼编码保存起来,以便在解压时使用。通过使用哈夫曼编码,我们可以实现对原始ASCII文本的高效压缩和解压缩操作。
相关问题
C语言实现,针对给定文本文件,统计其中不同字符的发生频率,形成待编码的字符集和发生频率,并构建哈夫曼树,并根据哈夫曼树把字符集编码成0,1字符串的文本文件,再以二进制比特位编码成文本文件
好的,这是一个比较复杂的问题,需要分几个步骤来完成。首先,我们需要读取给定的文本文件,统计其中不同字符的出现频率。可以采用哈希表来实现这一功能,具体做法如下:
1. 定义一个长度为256的数组freq,表示ASCII码表中256个字符的出现频率,初始化为0。
2. 读取文本文件,每读取一个字符,就将对应的freq数组元素加1。
3. 统计完所有字符的出现频率后,根据freq数组构建哈夫曼树。
接下来是构建哈夫曼树的步骤,具体做法如下:
1. 将所有字符及其出现频率作为叶子节点,构建一个森林。
2. 从森林中找到两个频率最小的节点(可以使用最小堆来实现),将它们合并成一个新节点,并将新节点插入到森林中。
3. 重复步骤2,直到森林中只剩下一个节点,即为哈夫曼树的根节点。
接下来是根据哈夫曼树将字符集编码成0,1字符串的步骤,具体做法如下:
1. 从哈夫曼树的根节点开始,遍历哈夫曼树。
2. 遍历到一个叶子节点时,记录下该字符的编码(从根节点到叶子节点路径上的0,1序列),并将其存储到一个编码表中。
3. 遍历完整个哈夫曼树后,编码表中存储了每个字符的编码。
最后,将编码后的文件以二进制比特位编码成文本文件,具体做法如下:
1. 读取编码后的文件,将每个字符的编码从编码表中查找到。
2. 将每个字符的编码转换成二进制比特位,并将它们拼接成一个二进制串。
3. 将二进制串转换成字节数组,每8个比特位为一组,转换成对应的字节,并将字节写入到输出文件中。
以上是针对给定文本文件,统计其中不同字符的发生频率,形成待编码的字符集和发生频率,并构建哈夫曼树,并根据哈夫曼树把字符集编码成0,1字符串的文本文件,再以二进制比特位编码成文本文件的 C语言实现。
用C语言编写程序。基于哈夫曼树的数据压缩算法 描述:输入一串字符串,根据给定的字符串中字符出现的频率建立相应哈夫曼树,构造哈夫曼编码表,在此基础上可以对待压缩文件进行压缩(即编码),同时可以对压缩后的二进制编码文件进行解压(即译码)。 输入:多组数据,每组数据一行,为一个字符串(只考虑26个小写字母即可)。当输入字符串为“0”时,输入结束。 输出:每组数据输出2n+4行(n为输入串中字符类别的个数)。第一行为统计出来的字符出现频率(只输出存在的字符,格式为:字符:频度),每两组字符之间用一个空格分隔,字符按照ASCII码从小到大的顺序排列。第二行至第2n行为哈夫曼树的存储结构的终态(形如教材139页表5.2(b),一行当中的数据用空格分隔)。第2n+2行为每个字符的哈夫曼编码(只输出存在的字符,格式为:字符:编码),每两组字符之间用一个空格分隔,字符按照ASCII码从小到大的顺序排列。第2n+3行为编码后的字符串,第2n+4行为解码后的字符串(与输入的字符串相同)。
以下为C语言代码实现:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_CHAR_NUM 26 // 最多只考虑26个小写字母
#define MAX_TREE_NODE_NUM (2 * MAX_CHAR_NUM - 1)
#define MAX_CODE_LENGTH 20
typedef struct TreeNode {
int weight;
int parent;
int left_child;
int right_child;
} TreeNode;
typedef struct Code {
char ch;
char code[MAX_CODE_LENGTH + 1];
} Code;
int get_freq(char *str, int freq[]) {
int len = strlen(str);
int i, idx, cnt = 0;
for (i = 0; i < len; i++) {
idx = str[i] - 'a';
if (freq[idx] == 0) cnt++;
freq[idx]++;
}
return cnt;
}
void init_tree(TreeNode *tree, int n) {
int i;
for (i = 0; i < n; i++) {
tree[i].weight = 0;
tree[i].parent = -1;
tree[i].left_child = -1;
tree[i].right_child = -1;
}
}
void build_tree(TreeNode *tree, int freq[], int n) {
int i, j, idx1, idx2, min1, min2;
for (i = 0; i < n - 1; i++) {
min1 = min2 = 0x7fffffff;
idx1 = idx2 = -1;
for (j = 0; j < n + i; j++) {
if (tree[j].parent == -1) {
if (tree[j].weight < min1) {
min2 = min1;
idx2 = idx1;
min1 = tree[j].weight;
idx1 = j;
} else if (tree[j].weight < min2) {
min2 = tree[j].weight;
idx2 = j;
}
}
}
tree[idx1].parent = n + i;
tree[idx2].parent = n + i;
tree[n + i].weight = min1 + min2;
tree[n + i].left_child = idx1;
tree[n + i].right_child = idx2;
}
}
void get_code(TreeNode *tree, Code code[], int n) {
int i, j, p, k;
char tmp[MAX_CODE_LENGTH + 1];
for (i = 0; i < n; i++) {
p = i;
k = 0;
while (tree[p].parent != -1) {
if (tree[tree[p].parent].left_child == p) {
tmp[k++] = '0';
} else {
tmp[k++] = '1';
}
p = tree[p].parent;
}
tmp[k] = '\0';
code[i].ch = i + 'a';
for (j = 0; j < k; j++) {
code[i].code[k - 1 - j] = tmp[j];
}
code[i].code[k] = '\0';
}
}
void encode(char *str, Code code[], int n, char *enc_str) {
int len = strlen(str);
int i, j, idx;
char *p = enc_str;
for (i = 0; i < len; i++) {
idx = str[i] - 'a';
for (j = 0; j < strlen(code[idx].code); j++) {
*p++ = code[idx].code[j];
}
}
*p = '\0';
}
void decode(char *enc_str, TreeNode *tree, int n, char *dec_str) {
int len = strlen(enc_str);
int i, p = 0;
for (i = 0; i < len; i++) {
if (enc_str[i] == '0') {
p = tree[p].left_child;
} else {
p = tree[p].right_child;
}
if (tree[p].left_child == -1 && tree[p].right_child == -1) {
*dec_str++ = p + 'a';
p = 0;
}
}
*dec_str = '\0';
}
int main() {
char str[1001], enc_str[1001], dec_str[1001];
int freq[MAX_CHAR_NUM];
TreeNode tree[MAX_TREE_NODE_NUM];
Code code[MAX_CHAR_NUM];
int n, i, j;
while (1) {
scanf("%s", str);
if (strcmp(str, "0") == 0) break;
n = get_freq(str, freq);
init_tree(tree, 2 * n - 1);
for (i = 0; i < n; i++) {
tree[i].weight = freq[i];
}
build_tree(tree, freq, n);
get_code(tree, code, n);
// 输出字符出现频率
for (i = 0; i < n; i++) {
if (freq[i] > 0) {
printf("%c:%d ", i + 'a', freq[i]);
}
}
printf("\n");
// 输出哈夫曼树的存储结构
for (i = 0; i < 2 * n - 1; i++) {
printf("%d %d %d %d\n", tree[i].weight, tree[i].parent, tree[i].left_child, tree[i].right_child);
}
// 输出编码
for (i = 0; i < n; i++) {
if (strlen(code[i].code) > 0) {
printf("%c:%s ", code[i].ch, code[i].code);
}
}
printf("\n");
// 对字符串进行编码
encode(str, code, n, enc_str);
printf("%s\n", enc_str);
// 对编码进行解码
decode(enc_str, tree, n, dec_str);
printf("%s\n", dec_str);
}
return 0;
}
```
阅读全文