Обновить sk1/compressor.c
This commit is contained in:
parent
10cc53b3bb
commit
5ba38bda7b
@ -4,46 +4,76 @@
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
// 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) {
|
||||
struct MinHeapNode* t = *a;
|
||||
*a = *b;
|
||||
*b = t;
|
||||
}
|
||||
|
||||
// MinHeapify function
|
||||
// MinHeapify
|
||||
void minHeapify(struct MinHeap* minHeap, int idx) {
|
||||
int smallest = idx;
|
||||
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* temp = minHeap->array[0];
|
||||
minHeap->array[0] = minHeap->array[minHeap->size - 1];
|
||||
@ -70,10 +100,11 @@ 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;
|
||||
@ -81,66 +112,39 @@ 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;
|
||||
buildMinHeap(minHeap);
|
||||
for (int i = (minHeap->size - 2) / 2; i >= 0; --i)
|
||||
minHeapify(minHeap, i);
|
||||
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 *left, *right, *top;
|
||||
struct MinHeap* minHeap = createAndBuildMinHeap(data, freq, size);
|
||||
|
||||
while (!isSizeOne(minHeap)) {
|
||||
while (minHeap->size > 1) {
|
||||
left = 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->left = left;
|
||||
top->right = right;
|
||||
|
||||
insertMinHeap(minHeap, top);
|
||||
}
|
||||
|
||||
// Extract the final node, which is the root of the Huffman tree
|
||||
struct MinHeapNode* root = extractMin(minHeap);
|
||||
|
||||
// Free the MinHeap structure
|
||||
free(minHeap->array);
|
||||
free(minHeap);
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
// Print Huffman Codes to a map
|
||||
// Сохранение кодов
|
||||
void storeCodes(struct MinHeapNode* root, char** codes, char* currentCode, int top) {
|
||||
if (root->left) {
|
||||
currentCode[top] = '0';
|
||||
@ -152,11 +156,15 @@ void storeCodes(struct MinHeapNode* root, char** codes, char* currentCode, int t
|
||||
}
|
||||
if (!(root->left) && !(root->right)) {
|
||||
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
|
||||
int compressFile(const char* input_file_name, const char* output_file_name) {
|
||||
FILE* inputFile = fopen(input_file_name, "rb");
|
||||
|
Loading…
Reference in New Issue
Block a user