Обновить sk1/compressor.c
This commit is contained in:
parent
10cc53b3bb
commit
5ba38bda7b
@ -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");
|
||||||
|
Loading…
Reference in New Issue
Block a user