#include #include #include #define MAX_TREE_HT 256 // Узел дерева Хаффмана struct MinHeapNode { unsigned char data; unsigned freq; struct MinHeapNode *left, *right; }; // Минкуча struct MinHeap { unsigned size; unsigned capacity; struct MinHeapNode** array; }; // Функция для создания нового узла 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; } // Функция для создания Минкучи 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 void swapMinHeapNode(struct MinHeapNode** a, struct MinHeapNode** b) { struct MinHeapNode* t = *a; *a = *b; *b = t; } // MinHeapify void minHeapify(struct MinHeap* minHeap, int idx) { int smallest = idx; int left = 2 * idx + 1; int right = 2 * idx + 2; if (left < minHeap->size && minHeap->array[left]->freq < minHeap->array[smallest]->freq) smallest = left; if (right < minHeap->size && minHeap->array[right]->freq < minHeap->array[smallest]->freq) smallest = right; if (smallest != idx) { swapMinHeapNode(&minHeap->array[smallest], &minHeap->array[idx]); minHeapify(minHeap, smallest); } } // Извлечение минимального узла struct MinHeapNode* extractMin(struct MinHeap* minHeap) { struct MinHeapNode* temp = minHeap->array[0]; minHeap->array[0] = minHeap->array[minHeap->size - 1]; --minHeap->size; minHeapify(minHeap, 0); return temp; } // Вставка нового узла в Минкучу 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; } minHeap->array[i] = minHeapNode; } // Создание и построение Минкучи 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); return minHeap; } // Построение дерева Хаффмана 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) { 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; } // Сохранение кодов void storeCodes(struct MinHeapNode* root, char** codes, char* currentCode, int top) { if (root->left) { currentCode[top] = '0'; storeCodes(root->left, codes, currentCode, top + 1); } if (root->right) { currentCode[top] = '1'; storeCodes(root->right, codes, currentCode, top + 1); } 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) { FILE* inputFile = fopen(input_file_name, "rb"); if (!inputFile) { perror("Error opening input file"); return -1; } int freq[256] = {0}; unsigned char buffer; // Count frequency of each byte while (fread(&buffer, sizeof(unsigned char), 1, inputFile)) { freq[buffer]++; } rewind(inputFile); unsigned char data[256]; int frequencies[256], size = 0; for (int i = 0; i < 256; i++) { if (freq[i] > 0) { data[size] = (unsigned char)i; frequencies[size] = freq[i]; size++; } } struct MinHeapNode* root = buildHuffmanTree(data, frequencies, size); char* codes[256] = {0}; char currentCode[MAX_TREE_HT]; storeCodes(root, codes, currentCode, 0); FILE* outputFile = fopen(output_file_name, "wb"); if (!outputFile) { perror("Error opening output file"); fclose(inputFile); return -1; } // Write codes to output file fwrite(freq, sizeof(int), 256, outputFile); unsigned char byte = 0; int bitCount = 0; while (fread(&buffer, sizeof(unsigned char), 1, inputFile)) { char* code = codes[buffer]; for (int i = 0; code[i] != '\0'; i++) { byte = (byte << 1) | (code[i] - '0'); bitCount++; if (bitCount == 8) { fwrite(&byte, sizeof(unsigned char), 1, outputFile); byte = 0; bitCount = 0; } } } if (bitCount > 0) { byte <<= (8 - bitCount); fwrite(&byte, sizeof(unsigned char), 1, outputFile); } freeHuffmanTree(root); fclose(inputFile); fclose(outputFile); return 0; } // Decompress the file int decompressFile(const char* input_file_name, const char* output_file_name) { FILE* inputFile = fopen(input_file_name, "rb"); if (!inputFile) { perror("Error opening input file"); return -1; } int freq[256]; fread(freq, sizeof(int), 256, inputFile); unsigned char data[256]; int frequencies[256], size = 0; for (int i = 0; i < 256; i++) { if (freq[i] > 0) { data[size] = (unsigned char)i; frequencies[size] = freq[i]; size++; } } struct MinHeapNode* root = buildHuffmanTree(data, frequencies, size); FILE* outputFile = fopen(output_file_name, "wb"); if (!outputFile) { perror("Error opening output file"); fclose(inputFile); return -1; } struct MinHeapNode* current = root; unsigned char buffer; int bitCount = 0; while (fread(&buffer, sizeof(unsigned char), 1, inputFile)) { for (int i = 7; i >= 0; i--) { int bit = (buffer >> i) & 1; if (bit == 0) current = current->left; else current = current->right; if (!(current->left) && !(current->right)) { fwrite(¤t->data, sizeof(unsigned char), 1, outputFile); current = root; } } } freeHuffmanTree(root); fclose(inputFile); fclose(outputFile); return 0; } int compress_1(const char* input_file_name, const char* output_file_name){ if(compressFile(input_file_name, output_file_name) == 0){ printf("Succsses!"); } return 0; } int decompress_1(const char* input_file_name, const char* output_file_name){ if(decompressFile(input_file_name, output_file_name) == 0){ printf("Succsses!"); } return 0; } int compress_2(const char* input_file_name, const char* output_file_name); int decompress_2(const char* input_file_name, const char* output_file_name);