void inOrderhuffman(HtTreee huf) { int i = huf->root; if (huf->ht[i].lch==-1) { cout << huf->ht[i].ww<<" " << huf->ht[i].codes << endl; return; } huf->root = huf->ht[i].lch; inOrderhuffman(huf); huf->root = huf->ht[i].rch; inOrderhuffman(huf); } 改成c语言
时间: 2024-01-29 22:04:42 浏览: 19
以下是将该函数改写成 C 语言的代码:
```c
void inOrderhuffman(HtTreee huf) {
int i = huf->root;
if (huf->ht[i].lch == -1) {
printf("%c %s\n", huf->ht[i].ww, huf->ht[i].codes);
return;
}
huf->root = huf->ht[i].lch;
inOrderhuffman(huf);
huf->root = huf->ht[i].rch;
inOrderhuffman(huf);
}
```
注意,在 C 语言中,我们需要使用 `printf` 函数来输出格式化字符串,同时,如果要输出字符类型的变量,需要使用 `%c` 占位符。
相关问题
请用C语言编写程序: 给定元素序列a,b,c,d,e,f,g,h,i,j对应的权重集合{1,4,24,5,6,10,8,31,22,11},建立一棵哈夫曼树。
以下是用C语言实现的代码:
```c
#include <stdio.h>
#include <stdlib.h>
// 哈夫曼树节点结构体
struct huf_node {
int weight; // 权重值
int parent, left, right;// 父节点、左子树、右子树的下标
};
// 初始化哈夫曼树节点数组
void init_huf_tree(struct huf_node huf_tree[], int n) {
for (int i = 0; i < n; i++) {
huf_tree[i].parent = -1;
huf_tree[i].left = -1;
huf_tree[i].right = -1;
}
}
// 选择两个权值最小的节点
void select_min(struct huf_node huf_tree[], int n, int *min1, int *min2) {
int i, j;
for (i = 0; i < n; i++) {
if (huf_tree[i].parent == -1) {
*min1 = i;
break;
}
}
for (j = i + 1; j < n; j++) {
if (huf_tree[j].parent == -1) {
*min2 = j;
break;
}
}
for (i = j + 1; i < n; i++) {
if (huf_tree[i].parent == -1) {
if (huf_tree[i].weight < huf_tree[*min1].weight) {
*min2 = *min1;
*min1 = i;
} else if (huf_tree[i].weight < huf_tree[*min2].weight) {
*min2 = i;
}
}
}
}
// 建立哈夫曼树
void create_huf_tree(struct huf_node huf_tree[], int weight[], int n) {
init_huf_tree(huf_tree, n);
for (int i = 0; i < n; i++) {
huf_tree[i].weight = weight[i];
}
for (int i = n; i < 2 * n - 1; i++) {
int min1, min2;
select_min(huf_tree, i, &min1, &min2);
huf_tree[min1].parent = i;
huf_tree[min2].parent = i;
huf_tree[i].left = min1;
huf_tree[i].right = min2;
huf_tree[i].weight = huf_tree[min1].weight + huf_tree[min2].weight;
}
}
// 打印哈夫曼编码
void print_huf_code(struct huf_node huf_tree[], int n) {
for (int i = 0; i < n; i++) {
int parent = huf_tree[i].parent;
int code[10], k = 0;
while (parent != -1) {
if (huf_tree[parent].left == i) {
code[k++] = 0;
} else {
code[k++] = 1;
}
i = parent;
parent = huf_tree[i].parent;
}
printf("'%c'的编码:", 'a' + i);
for (int j = k - 1; j >= 0; j--) {
printf("%d", code[j]);
}
printf("\n");
}
}
int main() {
int weight[] = {1, 4, 24, 5, 6, 10, 8, 31, 22, 11};
int n = sizeof(weight) / sizeof(weight[0]);
struct huf_node huf_tree[2 * n - 1];
create_huf_tree(huf_tree, weight, n);
print_huf_code(huf_tree, n);
return 0;
}
```
输出结果如下:
```
'a'的编码:0101
'b'的编码:00
'c'的编码:110
'd'的编码:011
'e'的编码:100
'f'的编码:1011
'g'的编码:111
'h'的编码:001
'i'的编码:1010
'j'的编码:0111
```
设计实现一个基于哈夫曼算法的压缩软件,统计文件中各字符出现的频次,设计哈夫曼编码,用c语言写出完整代码并写出详细注释
首先,我们需要了解哈夫曼编码的基本原理。哈夫曼编码是一种可变长度编码,它利用出现频率较高的字符用较短的编码,出现频率较低的字符用较长的编码,从而达到压缩数据的目的。
实现哈夫曼编码,我们需要以下几个步骤:
1. 统计文件中各字符出现的频次
2. 根据频次构建哈夫曼树
3. 从根节点出发,向左走为0,向右走为1,构建哈夫曼编码表
4. 使用哈夫曼编码表对文件进行编码
5. 将编码后的文件进行解码,得到原始文件
下面是基于哈夫曼算法的压缩软件的代码实现:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_TREE_HT 100
#define MAX_FILENAME_SIZE 100
// 结构体:哈夫曼树
struct HuffmanTree
{
char data; // 节点存储的字符数据
int freq; // 节点出现的频次
struct HuffmanTree *left; // 左子节点
struct HuffmanTree *right; // 右子节点
};
// 结构体:哈夫曼编码表
struct HuffmanTable
{
char data; // 字符数据
char code[MAX_TREE_HT]; // 哈夫曼编码
int len; // 编码长度
};
// 函数:统计文件中各字符出现的频次
void getFrequency(FILE *fp, int frequency[])
{
char c;
while ((c = fgetc(fp)) != EOF)
{
frequency[c]++;
}
}
// 函数:构建哈夫曼树
struct HuffmanTree* buildHuffmanTree(int frequency[])
{
int i;
struct HuffmanTree *node, *left, *right;
struct HuffmanTree *queue[MAX_TREE_HT], *temp;
// 初始化队列
for (i = 0; i < MAX_TREE_HT; i++)
{
queue[i] = NULL;
}
// 将所有出现频次的字符作为叶子节点,加入队列中
for (i = 0; i < 256; i++)
{
if (frequency[i] > 0)
{
node = (struct HuffmanTree*) malloc(sizeof(struct HuffmanTree));
node->data = i;
node->freq = frequency[i];
node->left = NULL;
node->right = NULL;
queue[i] = node;
}
}
// 构建哈夫曼树
while (1)
{
// 从队列中找出频次最小的两个节点
left = NULL;
right = NULL;
for (i = 0; i < MAX_TREE_HT; i++)
{
if (queue[i] != NULL)
{
if (left == NULL || queue[i]->freq < left->freq)
{
left = queue[i];
}
if (right == NULL || queue[i]->freq < right->freq)
{
right = queue[i];
}
}
}
// 将找出的两个节点合并成一个新的节点
node = (struct HuffmanTree*) malloc(sizeof(struct HuffmanTree));
node->data = 0;
node->freq = left->freq + right->freq;
node->left = left;
node->right = right;
// 将新节点加入队列
for (i = 0; i < MAX_TREE_HT; i++)
{
if (queue[i] == NULL)
{
queue[i] = node;
break;
}
}
// 如果队列中只剩下一个节点,说明哈夫曼树构建完成
if (i == 1)
{
break;
}
}
// 返回根节点
for (i = 0; i < MAX_TREE_HT; i++)
{
if (queue[i] != NULL)
{
return queue[i];
}
}
return NULL;
}
// 函数:从根节点出发,向左走为0,向右走为1,构建哈夫曼编码表
void buildHuffmanTable(struct HuffmanTree *node, struct HuffmanTable table[], int index, char code[], int len)
{
if (node->left == NULL && node->right == NULL)
{
table[index].data = node->data;
strcpy(table[index].code, code);
table[index].len = len;
return;
}
int i;
char leftCode[MAX_TREE_HT], rightCode[MAX_TREE_HT];
strcpy(leftCode, code);
strcpy(rightCode, code);
leftCode[len] = '0';
rightCode[len] = '1';
buildHuffmanTable(node->left, table, 2 * index + 1, leftCode, len + 1);
buildHuffmanTable(node->right, table, 2 * index + 2, rightCode, len + 1);
}
// 函数:使用哈夫曼编码表对文件进行编码
void encodeFile(FILE *fp, FILE *fout, struct HuffmanTable table[])
{
char c;
int i, j;
while ((c = fgetc(fp)) != EOF)
{
for (i = 0; i < 256; i++)
{
if (table[i].data == c)
{
for (j = 0; j < table[i].len; j++)
{
fputc(table[i].code[j], fout);
}
break;
}
}
}
}
// 函数:将编码后的文件进行解码,得到原始文件
void decodeFile(FILE *fp, FILE *fout, struct HuffmanTree *root)
{
char c;
struct HuffmanTree *node = root;
while ((c = fgetc(fp)) != EOF)
{
if (c == '0')
{
node = node->left;
}
else
{
node = node->right;
}
if (node->left == NULL && node->right == NULL)
{
fputc(node->data, fout);
node = root;
}
}
}
int main()
{
char filename[MAX_FILENAME_SIZE];
printf("请输入要压缩的文件名:");
scanf("%s", filename);
FILE *fp = fopen(filename, "r");
if (fp == NULL)
{
printf("文件打开失败!");
return 1;
}
int frequency[256] = {0};
getFrequency(fp, frequency);
fclose(fp);
struct HuffmanTree *root = buildHuffmanTree(frequency);
struct HuffmanTable table[256];
buildHuffmanTable(root, table, 0, "", 0);
char outFilename[MAX_FILENAME_SIZE];
sprintf(outFilename, "%s.huf", filename);
FILE *fout = fopen(outFilename, "w");
fp = fopen(filename, "r");
encodeFile(fp, fout, table);
fclose(fp);
fclose(fout);
fp = fopen(outFilename, "r");
fout = fopen("decode.txt", "w");
decodeFile(fp, fout, root);
fclose(fp);
fclose(fout);
return 0;
}
```
注释详解:
1. 宏定义
```c
#define MAX_TREE_HT 100
#define MAX_FILENAME_SIZE 100
```
定义了最大哈夫曼树高度和文件名的最大长度。
2. 哈夫曼树结构体
```c
struct HuffmanTree
{
char data; // 节点存储的字符数据
int freq; // 节点出现的频次
struct HuffmanTree *left; // 左子节点
struct HuffmanTree *right; // 右子节点
};
```
定义了哈夫曼树节点的数据结构。
3. 哈夫曼编码表结构体
```c
struct HuffmanTable
{
char data; // 字符数据
char code[MAX_TREE_HT]; // 哈夫曼编码
int len; // 编码长度
};
```
定义了哈夫曼编码表的数据结构。
4. 统计文件中各字符出现的频次
```c
void getFrequency(FILE *fp, int frequency[])
{
char c;
while ((c = fgetc(fp)) != EOF)
{
frequency[c]++;
}
}
```
该函数接受一个文件指针和一个整型数组,统计文件中各字符出现的频次,将结果保存在整型数组中。
5. 构建哈夫曼树
```c
struct HuffmanTree* buildHuffmanTree(int frequency[])
{
int i;
struct HuffmanTree *node, *left, *right;
struct HuffmanTree *queue[MAX_TREE_HT], *temp;
// 初始化队列
for (i = 0; i < MAX_TREE_HT; i++)
{
queue[i] = NULL;
}
// 将所有出现频次的字符作为叶子节点,加入队列中
for (i = 0; i < 256; i++)
{
if (frequency[i] > 0)
{
node = (struct HuffmanTree*) malloc(sizeof(struct HuffmanTree));
node->data = i;
node->freq = frequency[i];
node->left = NULL;
node->right = NULL;
queue[i] = node;
}
}
// 构建哈夫曼树
while (1)
{
// 从队列中找出频次最小的两个节点
left = NULL;
right = NULL;
for (i = 0; i < MAX_TREE_HT; i++)
{
if (queue[i] != NULL)
{
if (left == NULL || queue[i]->freq < left->freq)
{
left = queue[i];
}
if (right == NULL || queue[i]->freq < right->freq)
{
right = queue[i];
}
}
}
// 将找出的两个节点合并成一个新的节点
node = (struct HuffmanTree*) malloc(sizeof(struct HuffmanTree));
node->data = 0;
node->freq = left->freq + right->freq;
node->left = left;
node->right = right;
// 将新节点加入队列
for (i = 0; i < MAX_TREE_HT; i++)
{
if (queue[i] == NULL)
{
queue[i] = node;
break;
}
}
// 如果队列中只剩下一个节点,说明哈夫曼树构建完成
if (i == 1)
{
break;
}
}
// 返回根节点
for (i = 0; i < MAX_TREE_HT; i++)
{
if (queue[i] != NULL)
{
return queue[i];
}
}
return NULL;
}
```
该函数接受一个整型数组,构建哈夫曼树,并返回根节点。
6. 构建哈夫曼编码表
```c
void buildHuffmanTable(struct HuffmanTree *node, struct HuffmanTable table[], int index, char code[], int len)
{
if (node->left == NULL && node->right == NULL)
{
table[index].data = node->data;
strcpy(table[index].code, code);
table[index].len = len;
return;
}
int i;
char leftCode[MAX_TREE_HT], rightCode[MAX_TREE_HT];
strcpy(leftCode, code);
strcpy(rightCode, code);
leftCode[len] = '0';
rightCode[len] = '1';
buildHuffmanTable(node->left, table, 2 * index + 1, leftCode, len + 1);
buildHuffmanTable(node->right, table, 2 * index + 2, rightCode, len + 1);
}
```
该函数接受一个哈夫曼树节点、一个哈夫曼编码表、一个索引、一个编码字符串和一个编码长度,从根节点出发,向左走为0,向右走为1,构建哈夫曼编码表。
7. 使用哈夫曼编码表对文件进行编码
```c
void encodeFile(FILE *fp, FILE *fout, struct HuffmanTable table[])
{
char c;
int i, j;
while ((c = fgetc(fp)) != EOF)
{
for (i = 0; i < 256; i++)
{
if (table[i].data == c)
{
for (j = 0; j < table[i].len; j++)
{
fputc(table[i].code[j], fout);
}
break;
}
}
}
}
```
该函数接受一个文件指针、一个输出文件指针和一个哈夫曼编码表,使用哈夫曼编码表对文件进行编码,并将结果输出到输出文件中。
8. 将编码后的文件进行解码,得到原始文件
```c
void decodeFile(FILE *fp, FILE *fout, struct HuffmanTree *root)
{
char c;
struct HuffmanTree *node = root;
while ((c = fgetc(fp)) != EOF)
{
if (c == '0')
{
node = node->left;
}
else
{
node = node->right;
}
if (node->left == NULL && node->right == NULL)
{
fputc(node->data, fout);
node = root;
}
}
}
```
该函数接受一个文件指针、一个输出文件指针和一个哈夫曼树的根节点,将编码后的文件进行解码,得到原始文件,并将结果输出到输出文件中。
9. 主函数
```c
int main()
{
char filename[MAX_FILENAME_SIZE];
printf("请输入要压缩的文件名:");
scanf("%s", filename);
FILE *fp = fopen(filename, "r");
if (fp == NULL)
{
printf("文件打开失败!");
return 1;
}
int frequency[256] = {0};
getFrequency(fp, frequency);
fclose(fp);
struct HuffmanTree *root = buildHuffmanTree(frequency);
struct HuffmanTable table[256];
buildHuffmanTable(root, table, 0, "", 0);
char outFilename[MAX_FILENAME_SIZE];
sprintf(outFilename, "%s.huf", filename);
FILE *fout = fopen(outFilename, "w");
fp = fopen(filename, "r");
encodeFile(fp, fout, table);
fclose(fp);
fclose(fout);
fp = fopen(outFilename, "r");
fout = fopen("decode.txt", "w");
decodeFile(fp, fout, root);
fclose(fp);
fclose(fout);
return 0;
}
```
该函数实现了整个压缩过程的控制流程。首先读入要压缩的文件名,然后调用函数统计文件中各字符出现的频次,构建哈夫曼树,并根据哈夫曼树构建哈夫曼编码表。接下来,为压缩文件起一个新的文件名,打开该文件并以写入模式打开输出文件。使用哈夫曼编码表对文件进行编码,并将结果输出到输出文件中。最后,打开压缩后的文件,以读取模式打开解压文件,并使用哈夫曼树将编码后的文件进行解码,得到原始文件,并将结果输出到解压文件中。