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

This commit is contained in:
Yevhen Kozirovskyi 2025-01-19 17:29:02 +00:00
parent 10cc53b3bb
commit 5ba38bda7b

View File

@ -4,46 +4,76 @@
#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 function // MinHeapify
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;
@ -61,7 +91,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];
@ -70,10 +100,11 @@ 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;
@ -81,66 +112,39 @@ 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;
buildMinHeap(minHeap); for (int i = (minHeap->size - 2) / 2; i >= 0; --i)
minHeapify(minHeap, i);
return minHeap; return minHeap;
} }
// Build Huffman Tree // Построение дерева Хаффмана
void freeHuffmanTree(struct MinHeapNode* root) {
if (root == NULL) {
return;
}
freeHuffmanTree(root->left);
freeHuffmanTree(root->right);
free(root);
}
// Build Huffman Tree with memory management
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 (!isSizeOne(minHeap)) { while (minHeap->size > 1) {
left = extractMin(minHeap); left = extractMin(minHeap);
right = extractMin(minHeap); right = extractMin(minHeap);
// Create a new internal node with frequency equal to the sum of the two nodes
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);
} }
// Extract the final node, which is the root of the Huffman tree
struct MinHeapNode* root = extractMin(minHeap); struct MinHeapNode* root = extractMin(minHeap);
// Free the MinHeap structure
free(minHeap->array); free(minHeap->array);
free(minHeap); free(minHeap);
return root; 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';
@ -152,11 +156,15 @@ 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';
if (root->data < 256) { // Ensure data is within bounds 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");