Обновить sk1/compressor.c

This commit is contained in:
Yevhen Kozirovskyi 2025-01-19 17:39:39 +00:00
parent 5ba38bda7b
commit 4f7f2b98c9

View File

@ -4,76 +4,46 @@
#define MAX_TREE_HT 256 #define MAX_TREE_HT 256
// Узел дерева Хаффмана // A Huffman tree node
struct MinHeapNode { struct MinHeapNode {
unsigned char data; unsigned char data;
unsigned freq; unsigned freq;
struct MinHeapNode *left, *right; struct MinHeapNode *left, *right;
}; };
// Минкуча // A MinHeap
struct MinHeap { struct MinHeap {
unsigned size; unsigned size;
unsigned capacity; unsigned capacity;
struct MinHeapNode** array; struct MinHeapNode** array;
}; };
// Функция для создания нового узла // Function to create a new node
struct MinHeapNode* createNode(unsigned char data, unsigned freq) { struct MinHeapNode* createNode(unsigned char data, unsigned freq) {
struct MinHeapNode* temp = (struct MinHeapNode*)malloc(sizeof(struct MinHeapNode)); struct MinHeapNode* temp = (struct MinHeapNode*)malloc(sizeof(struct MinHeapNode));
if (!temp) {
perror("Ошибка выделения памяти для узла дерева");
exit(EXIT_FAILURE);
}
temp->data = data; temp->data = data;
temp->freq = freq; temp->freq = freq;
temp->left = temp->right = NULL; temp->left = temp->right = NULL;
return temp; return temp;
} }
// Функция для создания Минкучи // Function to create a MinHeap
struct MinHeap* createMinHeap(unsigned capacity) { struct MinHeap* createMinHeap(unsigned capacity) {
struct MinHeap* minHeap = (struct MinHeap*)malloc(sizeof(struct MinHeap)); struct MinHeap* minHeap = (struct MinHeap*)malloc(sizeof(struct MinHeap));
if (!minHeap) {
perror("Ошибка выделения памяти для Минкучи");
exit(EXIT_FAILURE);
}
minHeap->size = 0; minHeap->size = 0;
minHeap->capacity = capacity; minHeap->capacity = capacity;
minHeap->array = (struct MinHeapNode**)malloc(minHeap->capacity * sizeof(struct MinHeapNode*)); minHeap->array = (struct MinHeapNode**)malloc(minHeap->capacity * sizeof(struct MinHeapNode*));
if (!minHeap->array) {
perror("Ошибка выделения памяти для массива Минкучи");
free(minHeap);
exit(EXIT_FAILURE);
}
return minHeap; return minHeap;
} }
// Функция для освобождения памяти дерева // Swap function
void freeHuffmanTree(struct MinHeapNode* root) {
if (!root) return;
freeHuffmanTree(root->left);
freeHuffmanTree(root->right);
free(root);
}
// Освобождение памяти массива кодов
void freeCodes(char** codes) {
for (int i = 0; i < 256; i++) {
if (codes[i]) {
free(codes[i]);
}
}
}
// Swap
void swapMinHeapNode(struct MinHeapNode** a, struct MinHeapNode** b) { void swapMinHeapNode(struct MinHeapNode** a, struct MinHeapNode** b) {
struct MinHeapNode* t = *a; struct MinHeapNode* t = *a;
*a = *b; *a = *b;
*b = t; *b = t;
} }
// MinHeapify // MinHeapify function
void minHeapify(struct MinHeap* minHeap, int idx) { void minHeapify(struct MinHeap* minHeap, int idx) {
int smallest = idx; int smallest = idx;
int left = 2 * idx + 1; int left = 2 * idx + 1;
@ -91,7 +61,7 @@ void minHeapify(struct MinHeap* minHeap, int idx) {
} }
} }
// Извлечение минимального узла // Extract minimum value node from heap
struct MinHeapNode* extractMin(struct MinHeap* minHeap) { struct MinHeapNode* extractMin(struct MinHeap* minHeap) {
struct MinHeapNode* temp = minHeap->array[0]; struct MinHeapNode* temp = minHeap->array[0];
minHeap->array[0] = minHeap->array[minHeap->size - 1]; minHeap->array[0] = minHeap->array[minHeap->size - 1];
@ -100,11 +70,10 @@ struct MinHeapNode* extractMin(struct MinHeap* minHeap) {
return temp; return temp;
} }
// Вставка нового узла в Минкучу // Insert a new node to MinHeap
void insertMinHeap(struct MinHeap* minHeap, struct MinHeapNode* minHeapNode) { void insertMinHeap(struct MinHeap* minHeap, struct MinHeapNode* minHeapNode) {
++minHeap->size; ++minHeap->size;
int i = minHeap->size - 1; int i = minHeap->size - 1;
while (i && minHeapNode->freq < minHeap->array[(i - 1) / 2]->freq) { while (i && minHeapNode->freq < minHeap->array[(i - 1) / 2]->freq) {
minHeap->array[i] = minHeap->array[(i - 1) / 2]; minHeap->array[i] = minHeap->array[(i - 1) / 2];
i = (i - 1) / 2; i = (i - 1) / 2;
@ -112,39 +81,47 @@ void insertMinHeap(struct MinHeap* minHeap, struct MinHeapNode* minHeapNode) {
minHeap->array[i] = minHeapNode; minHeap->array[i] = minHeapNode;
} }
// Создание и построение Минкучи // Build the MinHeap
void buildMinHeap(struct MinHeap* minHeap) {
int n = minHeap->size - 1;
for (int i = (n - 1) / 2; i >= 0; --i)
minHeapify(minHeap, i);
}
// Check if size is 1
int isSizeOne(struct MinHeap* minHeap) {
return (minHeap->size == 1);
}
// Create and build a MinHeap
struct MinHeap* createAndBuildMinHeap(unsigned char data[], int freq[], int size) { struct MinHeap* createAndBuildMinHeap(unsigned char data[], int freq[], int size) {
struct MinHeap* minHeap = createMinHeap(size); struct MinHeap* minHeap = createMinHeap(size);
for (int i = 0; i < size; ++i) for (int i = 0; i < size; ++i)
minHeap->array[i] = createNode(data[i], freq[i]); minHeap->array[i] = createNode(data[i], freq[i]);
minHeap->size = size; minHeap->size = size;
for (int i = (minHeap->size - 2) / 2; i >= 0; --i) buildMinHeap(minHeap);
minHeapify(minHeap, i);
return minHeap; return minHeap;
} }
// Построение дерева Хаффмана // Build Huffman Tree
struct MinHeapNode* buildHuffmanTree(unsigned char data[], int freq[], int size) { struct MinHeapNode* buildHuffmanTree(unsigned char data[], int freq[], int size) {
struct MinHeapNode *left, *right, *top; struct MinHeapNode *left, *right, *top;
struct MinHeap* minHeap = createAndBuildMinHeap(data, freq, size); struct MinHeap* minHeap = createAndBuildMinHeap(data, freq, size);
while (minHeap->size > 1) { while (!isSizeOne(minHeap)) {
left = extractMin(minHeap); left = extractMin(minHeap);
right = extractMin(minHeap); right = extractMin(minHeap);
top = createNode('$', left->freq + right->freq); top = createNode('$', left->freq + right->freq);
top->left = left; top->left = left;
top->right = right; top->right = right;
insertMinHeap(minHeap, top); insertMinHeap(minHeap, top);
} }
return extractMin(minHeap);
struct MinHeapNode* root = extractMin(minHeap);
free(minHeap->array);
free(minHeap);
return root;
} }
// Сохранение кодов // Print Huffman Codes to a map
void storeCodes(struct MinHeapNode* root, char** codes, char* currentCode, int top) { void storeCodes(struct MinHeapNode* root, char** codes, char* currentCode, int top) {
if (root->left) { if (root->left) {
currentCode[top] = '0'; currentCode[top] = '0';
@ -157,14 +134,9 @@ void storeCodes(struct MinHeapNode* root, char** codes, char* currentCode, int t
if (!(root->left) && !(root->right)) { if (!(root->left) && !(root->right)) {
currentCode[top] = '\0'; currentCode[top] = '\0';
codes[root->data] = strdup(currentCode); codes[root->data] = strdup(currentCode);
if (!codes[root->data]) {
perror("Ошибка выделения памяти для кодов");
exit(EXIT_FAILURE);
}
} }
} }
// Compress the input file using Huffman Coding // Compress the input file using Huffman Coding
int compressFile(const char* input_file_name, const char* output_file_name) { int compressFile(const char* input_file_name, const char* output_file_name) {
FILE* inputFile = fopen(input_file_name, "rb"); FILE* inputFile = fopen(input_file_name, "rb");
@ -225,7 +197,7 @@ int compressFile(const char* input_file_name, const char* output_file_name) {
byte <<= (8 - bitCount); byte <<= (8 - bitCount);
fwrite(&byte, sizeof(unsigned char), 1, outputFile); fwrite(&byte, sizeof(unsigned char), 1, outputFile);
} }
freeHuffmanTree(root);
fclose(inputFile); fclose(inputFile);
fclose(outputFile); fclose(outputFile);
return 0; return 0;
@ -278,7 +250,7 @@ int decompressFile(const char* input_file_name, const char* output_file_name) {
} }
} }
} }
freeHuffmanTree(root);
fclose(inputFile); fclose(inputFile);
fclose(outputFile); fclose(outputFile);
return 0; return 0;