Обновить sk1/compressor.c
This commit is contained in:
parent
1a4906801b
commit
ddfe40aa8a
@ -24,7 +24,6 @@ typedef struct LZ77{
|
|||||||
char dalsi_znak;
|
char dalsi_znak;
|
||||||
} LZ77;
|
} LZ77;
|
||||||
|
|
||||||
// Функция для создания нового узла
|
|
||||||
Node* create_node(int symbol, unsigned int frequency) {
|
Node* create_node(int symbol, unsigned int frequency) {
|
||||||
Node* node = (Node*)malloc(sizeof(Node));
|
Node* node = (Node*)malloc(sizeof(Node));
|
||||||
node->symbol = symbol;
|
node->symbol = symbol;
|
||||||
@ -33,19 +32,16 @@ Node* create_node(int symbol, unsigned int frequency) {
|
|||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Функция для построения дерева Хаффмана
|
|
||||||
Node* build_huffman_tree(const unsigned int* frequencies) {
|
Node* build_huffman_tree(const unsigned int* frequencies) {
|
||||||
Node* nodes[MAX_SYMBOLS];
|
Node* nodes[MAX_SYMBOLS];
|
||||||
int node_count = 0;
|
int node_count = 0;
|
||||||
|
|
||||||
// Создаем узлы для всех символов с ненулевой частотой
|
|
||||||
for (int i = 0; i < MAX_SYMBOLS; i++) {
|
for (int i = 0; i < MAX_SYMBOLS; i++) {
|
||||||
if (frequencies[i] > 0) {
|
if (frequencies[i] > 0) {
|
||||||
nodes[node_count++] = create_node(i, frequencies[i]);
|
nodes[node_count++] = create_node(i, frequencies[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Объединяем узлы в дерево
|
|
||||||
while (node_count > 1) {
|
while (node_count > 1) {
|
||||||
// Сортируем узлы по частоте
|
// Сортируем узлы по частоте
|
||||||
for (int i = 0; i < node_count - 1; i++) {
|
for (int i = 0; i < node_count - 1; i++) {
|
||||||
@ -56,7 +52,6 @@ Node* build_huffman_tree(const unsigned int* frequencies) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Объединяем два узла с наименьшей частотой
|
|
||||||
Node* left = nodes[0];
|
Node* left = nodes[0];
|
||||||
Node* right = nodes[1];
|
Node* right = nodes[1];
|
||||||
Node* parent = create_node(-1, left->frequency + right->frequency);
|
Node* parent = create_node(-1, left->frequency + right->frequency);
|
||||||
@ -71,24 +66,22 @@ Node* build_huffman_tree(const unsigned int* frequencies) {
|
|||||||
return nodes[0];
|
return nodes[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Рекурсивная функция для генерации кодов Хаффмана
|
|
||||||
void generate_huffman_codes(Node* root, char* code, int depth, char codes[MAX_SYMBOLS][MAX_SYMBOLS]) {
|
void generate_huffman_codes(Node* root, char* code, int depth, char codes[MAX_SYMBOLS][MAX_SYMBOLS]) {
|
||||||
if (!root->left && !root->right) {
|
if (!root->left && !root->right) {
|
||||||
code[depth] = '\0'; // Завершаем код символа
|
code[depth] = '\0';
|
||||||
strcpy(codes[root->symbol], code);
|
strcpy(codes[root->symbol], code);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (root->left) {
|
if (root->left) {
|
||||||
code[depth] = '0'; // Добавляем бит '0' для левого поддерева
|
code[depth] = '0';
|
||||||
generate_huffman_codes(root->left, code, depth + 1, codes);
|
generate_huffman_codes(root->left, code, depth + 1, codes);
|
||||||
}
|
}
|
||||||
if (root->right) {
|
if (root->right) {
|
||||||
code[depth] = '1'; // Добавляем бит '1' для правого поддерева
|
code[depth] = '1';
|
||||||
generate_huffman_codes(root->right, code, depth + 1, codes);
|
generate_huffman_codes(root->right, code, depth + 1, codes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Функция для освобождения памяти, выделенной под дерево Хаффмана
|
|
||||||
void free_huffman_tree(Node* root) {
|
void free_huffman_tree(Node* root) {
|
||||||
if (!root) return;
|
if (!root) return;
|
||||||
free_huffman_tree(root->left);
|
free_huffman_tree(root->left);
|
||||||
@ -96,7 +89,6 @@ void free_huffman_tree(Node* root) {
|
|||||||
free(root);
|
free(root);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Функция сжатия данных с использованием алгоритма Хаффмана
|
|
||||||
int compress_1(const char* input_file, const char* output_file) {
|
int compress_1(const char* input_file, const char* output_file) {
|
||||||
FILE* input = fopen(input_file, "rb");
|
FILE* input = fopen(input_file, "rb");
|
||||||
FILE* output = fopen(output_file, "wb");
|
FILE* output = fopen(output_file, "wb");
|
||||||
@ -122,10 +114,9 @@ int compress_1(const char* input_file, const char* output_file) {
|
|||||||
char code[MAX_SYMBOLS] = {0};
|
char code[MAX_SYMBOLS] = {0};
|
||||||
generate_huffman_codes(root, code, 0, codes);
|
generate_huffman_codes(root, code, 0, codes);
|
||||||
|
|
||||||
// Записываем частоты в выходной файл
|
|
||||||
fwrite(frequencies, sizeof(frequencies[0]), MAX_SYMBOLS, output);
|
fwrite(frequencies, sizeof(frequencies[0]), MAX_SYMBOLS, output);
|
||||||
|
|
||||||
// Сжимаем данные
|
|
||||||
rewind(input);
|
rewind(input);
|
||||||
unsigned char current_byte = 0;
|
unsigned char current_byte = 0;
|
||||||
int bit_count = 0;
|
int bit_count = 0;
|
||||||
@ -145,7 +136,6 @@ int compress_1(const char* input_file, const char* output_file) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Записываем маркер EOF
|
|
||||||
char* eof_code = codes[256];
|
char* eof_code = codes[256];
|
||||||
for (size_t j = 0; eof_code[j] != '\0'; j++) {
|
for (size_t j = 0; eof_code[j] != '\0'; j++) {
|
||||||
current_byte = (current_byte << 1) | (eof_code[j] - '0');
|
current_byte = (current_byte << 1) | (eof_code[j] - '0');
|
||||||
@ -167,7 +157,6 @@ int compress_1(const char* input_file, const char* output_file) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Функция декомпрессии данных с использованием алгоритма Хаффмана
|
|
||||||
int decompress_1(const char* input_file, const char* output_file) {
|
int decompress_1(const char* input_file, const char* output_file) {
|
||||||
FILE* input = fopen(input_file, "rb");
|
FILE* input = fopen(input_file, "rb");
|
||||||
FILE* output = fopen(output_file, "wb");
|
FILE* output = fopen(output_file, "wb");
|
||||||
@ -182,7 +171,7 @@ int decompress_1(const char* input_file, const char* output_file) {
|
|||||||
unsigned char byte;
|
unsigned char byte;
|
||||||
int bit;
|
int bit;
|
||||||
|
|
||||||
// Читаем и декодируем символы
|
|
||||||
while (fread(&byte, 1, 1, input) == 1) {
|
while (fread(&byte, 1, 1, input) == 1) {
|
||||||
for (bit = 7; bit >= 0; bit--) {
|
for (bit = 7; bit >= 0; bit--) {
|
||||||
current = (byte & (1 << bit)) ? current->right : current->left;
|
current = (byte & (1 << bit)) ? current->right : current->left;
|
||||||
|
Loading…
Reference in New Issue
Block a user