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