#include #include #include #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)); 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)); minHeap->size = 0; minHeap->capacity = capacity; minHeap->array = (struct MinHeapNode**)malloc(minHeap->capacity * sizeof(struct MinHeapNode*)); return minHeap; } // Swap function void swapMinHeapNode(struct MinHeapNode** a, struct MinHeapNode** b) { struct MinHeapNode* t = *a; *a = *b; *b = t; } // MinHeapify function 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); } } // 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]; --minHeap->size; minHeapify(minHeap, 0); 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; } 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); return minHeap; } void freeMinHeap(struct MinHeap* minHeap) { for (int i = 0; i < minHeap->size; ++i) { free(minHeap->array[i]); } free(minHeap->array); free(minHeap); } void freeHuffmanCodes(char* codes[256]) { for (int i = 0; i < 256; ++i) { if (codes[i]) { free(codes[i]); } } } // 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 (!isSizeOne(minHeap)) { left = extractMin(minHeap); right = extractMin(minHeap); top = createNode('$', left->freq + right->freq); top->left = left; top->right = right; insertMinHeap(minHeap, top); } return extractMin(minHeap); } // Print Huffman Codes to a map void storeCodes(struct MinHeapNode* root, char** codes, char* currentCode, int top) { if (!root) return; 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); // Ensure memory is allocated } } // Updated compressFile function 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] = {0}; // Initialize to avoid garbage values 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]; if (!code) { fprintf(stderr, "Error: Undefined code for byte %u\n", buffer); fclose(inputFile); fclose(outputFile); return -1; } 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); } fclose(inputFile); fclose(outputFile); // Free memory for codes for (int i = 0; i < 256; i++) { if (codes[i]) free(codes[i]); } freeHuffmanCodes(codes); // Освободите память для кодов freeMinHeap(minHeap); // Освободите память для кучи 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; } } } 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);